From 69deb0c9474cc118517d4b107de2eb19e4799c6e Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 9 Jun 2021 07:41:05 +0100 Subject: [PATCH 1/8] Copy across some config from CC:T --- .editorconfig | 3 - .github/ISSUE_TEMPLATE/bug_report.md | 3 +- .github/matchers/checkstyle.json | 17 + .github/matchers/illuaminate.json | 18 + .github/matchers/junit.json | 15 + .github/workflows/main-ci.yml | 72 +- build.gradle | 53 +- config/checkstyle/checkstyle.xml | 164 ++ config/checkstyle/suppressions.xml | 12 + config/idea/codeInspectionSettings.xml | 2491 ++++++++++++++++++++++ config/idea/codeStyleSettings.xml | 61 + config/license/api.txt | 3 + config/license/main.txt | 3 + config/pre-commit/config.yml | 48 + config/pre-commit/illuaminate-lint.sh | 16 + gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 5 +- gradlew | 53 +- gradlew.bat | 43 +- 19 files changed, 3006 insertions(+), 74 deletions(-) create mode 100644 .github/matchers/checkstyle.json create mode 100644 .github/matchers/illuaminate.json create mode 100644 .github/matchers/junit.json create mode 100644 config/checkstyle/checkstyle.xml create mode 100644 config/checkstyle/suppressions.xml create mode 100644 config/idea/codeInspectionSettings.xml create mode 100644 config/idea/codeStyleSettings.xml create mode 100644 config/license/api.txt create mode 100644 config/license/main.txt create mode 100644 config/pre-commit/config.yml create mode 100755 config/pre-commit/illuaminate-lint.sh diff --git a/.editorconfig b/.editorconfig index f04c87852..779f99a12 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,6 +10,3 @@ insert_final_newline = true [*.md] trim_trailing_whitespace = false - -[*.properties] -insert_final_newline = false diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 67be8726d..f9cee6d08 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -11,5 +11,6 @@ labels: bug ## Useful information to include: - Minecraft version - - CC: Restitched version + - CC: Tweaked version + - Logs: These will be located in the `logs/` directory of your Minecraft instance. Please upload them as a gist or directly into this editor. - Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed. diff --git a/.github/matchers/checkstyle.json b/.github/matchers/checkstyle.json new file mode 100644 index 000000000..ca6e30e63 --- /dev/null +++ b/.github/matchers/checkstyle.json @@ -0,0 +1,17 @@ +{ + "problemMatcher": [ + { + "owner": "checkstyle", + "pattern": [ + { + "regexp": "^([a-z]+) ([\\w./-]+):(\\d+):(\\d+): (.*)$", + "severity": 1, + "file": 2, + "line": 3, + "column": 4, + "message": 5 + } + ] + } + ] +} diff --git a/.github/matchers/illuaminate.json b/.github/matchers/illuaminate.json new file mode 100644 index 000000000..f59036028 --- /dev/null +++ b/.github/matchers/illuaminate.json @@ -0,0 +1,18 @@ +{ + "problemMatcher": [ + { + "owner": "illuaminate", + "severity": "warning", + "pattern": [ + { + "regexp": "^([\\w./-]+):\\[(\\d+):(\\d+)\\-(?:\\d+):(?:\\d+)\\]: (.*) \\[([a-z:-]+)\\]$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + } + ] +} diff --git a/.github/matchers/junit.json b/.github/matchers/junit.json new file mode 100644 index 000000000..1655a5f66 --- /dev/null +++ b/.github/matchers/junit.json @@ -0,0 +1,15 @@ +{ + "problemMatcher": [ + { + "owner": "junit", + "pattern": [ + { + "regexp": "^## ([\\w./-]+):(\\d+): (.*)$", + "file": 1, + "line": 2, + "message": 3 + } + ] + } + ] +} diff --git a/.github/workflows/main-ci.yml b/.github/workflows/main-ci.yml index 133c74a4c..a144e94db 100644 --- a/.github/workflows/main-ci.yml +++ b/.github/workflows/main-ci.yml @@ -3,33 +3,55 @@ name: Build on: [push, pull_request] jobs: - build: - name: Build - runs-on: ubuntu-latest + build: + name: Build + runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Checkout submodules - run: git submodule update --init --recursive + steps: + - uses: actions/checkout@v2 - - name: Set up Java 8 - uses: actions/setup-java@v1 - with: - java-version: 8 + - 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: 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: Disable Gradle daemon + run: | + mkdir -p ~/.gradle + echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties - - name: Upload Jar - uses: actions/upload-artifact@v1 - with: - name: cc-restiched - path: build/libs + - name: Build with Gradle + run: | + ./gradlew assemble || ./gradlew assemble + ./gradlew build + + - name: Upload Jar + uses: actions/upload-artifact@v2 + with: + name: cc-restitched + path: build/libs + + - name: Parse test reports + run: ./tools/parse-reports.py + if: ${{ failure() }} + + - name: Cache pre-commit + uses: actions/cache@v2 + with: + path: ~/.cache/pre-commit + key: ${{ runner.os }}-pre-commit-${{ hashFiles('config/pre-commit/config.yml') }} + restore-keys: | + ${{ runner.os }}-pre-commit- + + - name: Run linters + run: | + pip install pre-commit + pre-commit run --config config/pre-commit/config.yml --show-diff-on-failure --all --color=always diff --git a/build.gradle b/build.gradle index 9d847ea70..686c19c8a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,8 @@ plugins { - id 'fabric-loom' version '0.6-SNAPSHOT' + id 'fabric-loom' version '0.7-SNAPSHOT' id 'maven-publish' + id "checkstyle" + id "com.github.hierynomus.license" version "0.15.0" } sourceCompatibility = JavaVersion.VERSION_1_8 @@ -22,10 +24,12 @@ repositories { } configurations { - compile.extendsFrom shade + implementation.extendsFrom shade } dependencies { + checkstyle "com.puppycrawl.tools:checkstyle:8.25" + minecraft "com.mojang:minecraft:${mc_version}" mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}:v2" modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}" @@ -37,7 +41,7 @@ dependencies { modImplementation "io.github.prospector:modmenu:${modmenu_version}" modImplementation "me.shedaniel.cloth.api:cloth-utils-v1:${cloth_api_version}" - compile 'com.electronwill.night-config:toml:3.6.3' + implementation 'com.electronwill.night-config:toml:3.6.3' implementation 'com.google.code.findbugs:jsr305:3.0.2' shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT' @@ -85,6 +89,49 @@ jar { from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) } } + +import com.hierynomus.gradle.license.tasks.LicenseCheck +import com.hierynomus.gradle.license.tasks.LicenseFormat + +license { + mapping("java", "SLASHSTAR_STYLE") + strictCheck true + + ext.year = Calendar.getInstance().get(Calendar.YEAR) +} + +[licenseMain, licenseFormatMain].forEach { + it.configure { + include("**/*.java") + exclude("dan200/computercraft/api/**") + header file('config/license/main.txt') + } +} + +[licenseTest, licenseFormatTest].forEach { + it.configure { + include("**/*.java") + header file('config/license/main.txt') + } +} + +gradle.projectsEvaluated { + tasks.withType(LicenseFormat) { + outputs.upToDateWhen { false } + } +} + + +task licenseAPI(type: LicenseCheck); +task licenseFormatAPI(type: LicenseFormat); +[licenseAPI, licenseFormatAPI].forEach { + it.configure { + source = sourceSets.main.java + include("dan200/computercraft/api/**") + header file('config/license/api.txt') + } +} + // configure the maven publication publishing { publications { diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 000000000..aaafdfd01 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml new file mode 100644 index 000000000..647da4baa --- /dev/null +++ b/config/checkstyle/suppressions.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/config/idea/codeInspectionSettings.xml b/config/idea/codeInspectionSettings.xml new file mode 100644 index 000000000..57b8ed0d7 --- /dev/null +++ b/config/idea/codeInspectionSettings.xml @@ -0,0 +1,2491 @@ + + + + diff --git a/config/idea/codeStyleSettings.xml b/config/idea/codeStyleSettings.xml new file mode 100644 index 000000000..9a1e0f1d4 --- /dev/null +++ b/config/idea/codeStyleSettings.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + diff --git a/config/license/api.txt b/config/license/api.txt new file mode 100644 index 000000000..5c1d391fe --- /dev/null +++ b/config/license/api.txt @@ -0,0 +1,3 @@ +This file is part of the public ComputerCraft API - http://www.computercraft.info +Copyright Daniel Ratcliffe, 2011-${year}. 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. diff --git a/config/license/main.txt b/config/license/main.txt new file mode 100644 index 000000000..bab494b2e --- /dev/null +++ b/config/license/main.txt @@ -0,0 +1,3 @@ +This file is part of ComputerCraft - http://www.computercraft.info +Copyright Daniel Ratcliffe, 2011-${year}. Do not distribute without permission. +Send enquiries to dratcliffe@gmail.com diff --git a/config/pre-commit/config.yml b/config/pre-commit/config.yml new file mode 100644 index 000000000..1f8ee9bcc --- /dev/null +++ b/config/pre-commit/config.yml @@ -0,0 +1,48 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-merge-conflict + + # Quick syntax checkers + - id: check-xml + - id: check-yaml + - id: check-toml + - id: check-json + exclude: "tsconfig\\.json$" + +- repo: https://github.com/editorconfig-checker/editorconfig-checker.python + rev: 2.3.5 + hooks: + - id: editorconfig-checker + args: ['-disable-indentation'] + exclude: "^(.*\\.(bat)|LICENSE)$" + +- repo: local + hooks: + - id: checkstyle + name: Check Java codestyle + files: ".*\\.java$" + language: system + entry: ./gradlew checkstyleMain checkstyleTest + pass_filenames: false + require_serial: true + - id: license + name: Check Java license headers + files: ".*\\.java$" + language: system + entry: ./gradlew licenseFormat + pass_filenames: false + require_serial: true + +exclude: | + (?x)^( + src/generated| + src/test/resources/test-rom/data/json-parsing/| + src/test/server-files/| + config/idea/ + ) diff --git a/config/pre-commit/illuaminate-lint.sh b/config/pre-commit/illuaminate-lint.sh new file mode 100755 index 000000000..ac7b762bf --- /dev/null +++ b/config/pre-commit/illuaminate-lint.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -e + +test -d bin || mkdir bin +test -f bin/illuaminate || curl -s -obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate +chmod +x bin/illuaminate + +if [ -n ${GITHUB_ACTIONS+x} ]; then + # Register a problem matcher (see https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md) + # for illuaminate. + echo "::add-matcher::.github/matchers/illuaminate.json" + trap 'echo "::remove-matcher owner=illuaminate::"' EXIT +fi + +./gradlew luaJavadoc +bin/illuaminate lint diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 23334 zcmX@GiTUt3<_+46yi-*#FWbq;z#z%Yz@R^Qg0k3TKSq&y6+^w`oW$bd-k{TYmmNfG zFYhQdT-Nf%wQ`C>yk}&W( z=H!SiF)WrZK6iEJ_jBjt@7FU_bnRvMykm36ZpL>H_x1bA^VgWLip|She7CqUYIUvN z1KH;*g?310FTU5)UT>RvK1Dxync(xzGv}6GO||i@%3HwQ_+hHyDY^7b8X|{}7v}vA zyno6h_@cVDyK?Gc@yd5x#~*}bT`s+3mAZX?iH3t(r<7&m+OQf$`%@mzFM7{ic~0fj zl9%qW>04ix-+HfMd^IfLWxU2z3ClGh|J;Q*cKy7ew#tPoCr0hbijx_fD#F z4&1u$JC*mMknV=^qq}k*Hk)PIi2jH&+H7fj?c19duQn?Se`vq7k)eF&tz9|18HXO% zKl=1z=d%h6dAI8?T(>lp)%}+~GW}J&<%7Kes{93W%Pkl$=v@pleii(Q^WxS`cN~-7 zX=lw(e-Y@K@23!4_42OM;;Qc(d#0{Bl65rZu+`f3+cysIRxt*~9X*&I;LXg!#lXP9 z!N9=a$dJjXvs#{&fkB0ffk77<&ocG5gN4H-{>v8M+@RB8sMXoD(aDoRSbuBShOl0Z z3#__~xm#}Oom5xmo2NG{P>IYZcopoJqOO* z+Bb;z6nB`FQ`~vR6a&>{srRQoI8HTCP7HJ7nVu4JtlH?= zgnH5AdwK-KQeqB<7VeRE@(WnkS`d4PT`0&%X@_F6jJayfjn23l6-VyGz#FH!7c21T zC3+sKV^nBc)RM}Uddg(yT*ECzGp9>7EiVZ!_cQ(>bW)q=Ur*=*p4*{!pKP9bNoo7@ zt**@)iC0f$9}_)$?PzuHi}GounKqE%ZgZ`!+mV` z^*nco{gHg96U|!R7SY^rb~?|z@=J34D&^+tdAUpH?eSQBGx+dw&wbrRQ}^30Ub`bn zsHDhjsYZ1jQaXH$Pn{;(UJEWbf|n9BW%{bMZ`J z5&E?Gxuxn-25Cz!oi!dmA{u#5tz5jI$(rk3S2DwDp=%;FP5z>H4%eR2+gg6=^|BDz z>{HB|LW>?4*Z8f~ifRhF9Tdu1AOFCcHU44tt0h&JjN3w=E!xMm?_h##%vvdv?hqcv zC(*3;A2v3<|JbnXjc9w$gN`Qo56XuxXlogKv0GoC`Dt4O@6$J#bKRm;yr;!p%Gl(u zHgE3LV;{f13d_Ivtn=Pgx9~NM4avG^d?(&_*;JUZ{MhW*R-uza=1&Z1{W$H^6>H`C zpeKH1Yu|hb`dsCq60Kg6Z9Cyq>e**%M`y3e-?VG_^NdalsZVD6bBcR~?o3^O<50j~ z+e=TbE#~@=`Yz>`&c=vGtnaLNc3t0gBVqTIZ8vk2wp4vQzh}vmd48WkZdaZbL;Z;pe!9`$)jQ z+S%ooq!C(@yP&@M%zuvCi~ng=E&BJNPwP-}V}`<>$xD6~} z`Kv4b>wj72-1n>Ad5UAhx7`bZUo0uscf8xq_hsSyI*T6VJ|5TgL4V8(1ysBCI$gZ4 z%qw_jiMWHVMWMAz*^FxM#|ErY2ekSwoOR!J?jrx9i5ik^4NFIf|k9Z z-cyfTd+sq@0Ty#Z zR%%?$n&7aU^P3@)mQ&y4I|{oB)!EWDZHk_=aZQq6#=tKu!Dz$sjpaCp#mSUA`z-ul zGN(LxUmo20pJ8$~+ehA|%u1ftEDQ`c*clic!6j%tJ14tKYFc7xPRZog5_0uRL+=Jl zhl>2an`6d(nk~pfW6HLMZKf<p^h* zuSNcT@ii}dIIhn8=9~UY{KwZt##W0TH_Jah-ecVNJnoSD@`lTXGv`!)pHqGAeYxGY zX9w-&?=yekxo0GJocn9WK~7D!r6*>n_|;!~IHmJ)#YRTXITL4XRy&utg7L6~;RMqU zlR7ox`sU1R{59i5Vo29#wqrao1_tK@3ilL6{@{_VJg>j}w4J`C(%vVZTUj42|9omj z;tFj}_bHVM5`B5)1vjFLWc#P<{ffIOKGo~qI+jDB>#D_THfB^`J#|d-p?Isb!3LR! z^S8uW*IS$|u-nPqc)aP&%p?x}O4UcVrfiQbTxeyl{m0Yp^@L@X??rbSAFYkHyFTS% z!nt(@C4Al5dtR|vyQXa@(p&4yw?2f$a?Y*Z>kI#PxGnXZlC{n0Kyy}VM&It#z@!Y% zXX`(?&MR}Bu+L=T>7Kq*b9mykPBQTH^3RrB`-e9ZwVbw5(4htYe=pxVR-? zkJ&NtEJ<~h@bbN)dvv(srUf@u74fd#8u7Julg%yTmwVXqt6$#vapLQu2#%cds$#hz zHdvs};IZNDuxuvr<`gXn6+Wa8&qBXdl!``+wyUZ1EPEt<@iFMZOQS}J{u=l7Ir3ok8KUzL|| zzMFTk%N)ZGvs$kg-aI6|BjPW5yBpKY^R zC#$ghN7=!Su&Ejl$xbJ(Rs`An`<8K?dPa% zJh<-H?Dt9jubeaHAM`2R+7`ZG@}5fWz@WBS%JK(iOnc@pIN4iY^8F$`rjuU5YxoW+ z{N#=Oc3etm>m1J9=DP~>oPst=yYNRkXI)=??(4<4cCr4g z6K368UoZ8P-SpJW88ctKiF2$yQ}T@MOG_QMdqclZu_)%$X&)R(t%{Tq`RIhVqt50C5 zUm4OTywgo-{xX-+O*2Y9WnP`}#;q!Hsz|W)%qhzzt!g%lD>&D1)uHktZ{X?drcIOX zeT?vYz3*b>;qJvRZ&|OtvAOFRzgd)g;KhIU7G6D`ol$7B{DRYwm@2z|^{e*!v34hd z+n()5ZM0q7<@ZL1nStQ|8v}z0w8&Aa54{^K6e#jP)Rb4+tsm3vv_B(>CuP@*Ds|M zx_@bz6E}%>>U(at-8(iI1CM)8${wrd@lQ^8F;sVjf@3qdh@C>X+rIc-O32XIN5MJ2CuIwB-uT zv=1c$sRd~j_ms``4|RE-j?$7a=MD81JmIJi?EfOOEsJ~qjL?q##(AeYuWv3owkq_1 ziSzRBXO!67E7^0SnR(tmXOKLyW1g{)SH#oW61kmBbLO|OnRr!nxHHLl&p0T|=`Sc~ zpqsy}usGIkqt%QzWDwlT- z`n+4eDS1WDv1il6C93phZEsPnoq9B)#b@c76HXc{OU?%zKE9{kqG_J;pO1=bAL(9v z(fzgBf0w_T2wRi?_LcIpI=ncuth2SGk8WOh`88R!0H_P)J!Sy)xy%7 zGfa49dfeE%FSKg9l)q(?=@I>i(~^su_^QNTAFLPM@UfbuO?wOXq$P#!OY6nAeP43p zf=l+))IU9GA66$YUT89#R90{Ir1gRRmd%r6zC928$oQ?iV?x+W_s|siL#Om)_Ev`M zc8&V9;%2kS?eDz%f~J4I@O0f>=eu|8Vzg`jR>s_Ft#1Djb8q8|BD>r#70mI9kF4+f zV3e<0B+t(ASp3nC+>c*`ryI=K(dO4xlq?jx#PHCsi@vjZjdeo`@2=|j>v)ItmCvzW zCr4$K+}6Aemv>(*;Lv#TaMpCc2Z?pu_q)R;ojr2EnP;8QV>!NJ%NO@o%028{R*#yg zR2WXyJ?3X%h)`f)P=sbGj(SLccWo4Bh4k^#x_*|8-UXG8LaHxXQe{Q>FH9<(G%aW1 zA{CE4E)%9`MotPpFsX$#>ETf)k+~LqZ%=f-)hNqRFPyV1Z}zgh*%lM$a7=N%?bUx` z?On5%g5N!EfAQ$w;_H8X@1za?dBhYPoVHwE|EuNZO!NGE)t~$7)55DB*Sm+uD=*Uh zv!*@l^83mc61A&k_HK9i{Cm+)=GK1~ob!Gu8~)h#;8*h0e@C3_z3vCTJTLOAm_PJV ze8mg>m%HVDG5wvI@h@t_-`G!qTc(V><>VuO`u zl0-lXTGLy z#ylS>&t;~+djxGoH-Dcg{Bg!g_g^~2SBxf|T$gdl?7)foC#)~;Jh?Z;HtopUjEL>N z0;}1p`M!UVduwTW<)%E>w{Hz=U(5Ynb5H2<^$V5t}wacJIztohw(Z-~ZjAK3$_^)nkQ}>0KQMclF(yH}6~@V}^yP zz?*k(WMwR_%D#EU)n-+1xLLpDsC4#>n!j_azl)|O6dgZvF>qtQXzVi6TSi$gC(gKN zl=!lqJ@3|K%uG~9(C2oHM z>*u}Z^EYL7oV=RomXJ~!Zj$$9$uWQFYYlZ)X&nD&C)%1Vi4HU@>(Hy#sqa!)A9W&S zMuuL-&Hl}IzwhdunrLh%BdHQR`eWof#^Ur^IP54~im5#+?oq_WwN}Io# zcJSYV#j07`-t-^iS?PFDSujy5X!Qh9O$ozEWhU=ltkR0ZsQ@Z_W) z0!lN_Zs0Rk4N=JW!22d@T7H>0mu6l|Yv6_n3%@M8`Er7!UGfd)i-m`MZdyJ*7~W+V z9Glm?SJQgpCP6l5`Qs&?B3aX(q&0v1r>f`k*EogFKjd!m?)ijc%r+}N3dmo55n1K6*!#<*W96R=J{U)Dc`H=a z<58E%Z2d`5x8Cc7z1pnDQumLlo9yz*?7g?Z{9$-v!DgN%$JFb8iuj#j&AI*~@0zKd z?kt1kj1L{h7TYW<2zgxnqvx1m;`is0&q7>SH$|>&$#oIw%g!lk$_(VIs49NhyV+*- zLHmX3e=E6}54~wQ^gS!5FerJpU|7(PHOGYKT=+4k+JVx=IoN6IxpT;s-8jkPeX>C#-2|L zUf8P4YB$!lW4W)_(9|$BQu%kGmP6vbCyV}G64;;nOL*5*lRr-CvCFT|JeBeR-DJkdcb?wD| z@}DUA;2t0q_NBz@1IwRUL*@>xX{w70mfBAZmf%|8)@pUR>)vyR9oES$Zu*x)d+pE2 zU;GhR$0H{;o6jLd=Yk$%)Z^nn7kiwEyy4n<*3qI@|HJV)E$8ER>uq18#k`w2P3=zK zyqXW8KRA2mKj}YQ-^~1bc6rtx5&PH!)9Yh*t>92H{>l0^=E0o`odPSVewJ@9x8?b( z@yNJ;SYvZJTUa0=-6#9_)x)z=tR~LScl|T#i@(d;jjWHve1AP&_SS!y5T|gKQr!hL z#=d{f&UZiTHV@v#xV*%;A|%}7P4R~qm7m5^^-c_pEH4g3vad5ue{!IpG|j@!JMc`3 zLa|kS#RYAJ*Fqb@*Z6N+vV$h#621DPipGyOZArL-oy&E2HO9B^=`F(U9xC#=#4xZ`-0QYPw4E>sNT4` z?(sd5cfU9H-HLd!FZ_@0QnAyrmFFCrZdcX@+)`A1JyB*aSDfaFxl1eaH1|YxSF0RR z+E(_>m!Xc!X`AYO>H1Tz`nPu{`a149xzg*w<_|SxF%=I_1sts|H<6rUYx!CKXDw5E z(KH<`r?xuIu!zt%Nj-bb|4HoR*1Y+dIls6}>!u-F=AmV-#qZ{|^Ksrx6%M=N7Nq&X zF`(*J`C+A|+aHShO&`vfDe^us$%yab+4nEq-pl;SE&ef=`=`^NRdcQDeWb+vmdW^d z9G|NEVc~}viU)!m|1X%i#dxnB!;Z_BUF}x9koA;&G(#YC-~CJO$Di_Af1Ed|+)njJ zeYDz|vc(NwB8vR%Qtp=MB(HI?6TDKh-!mzCnHkrDi{|ssR)#iCc3Eff=-Pg7h0R4eAyoyb)cW{G$4(^voK&H#Q%GT9>o$>A%o^v5sZ2 zqgK7L_`IjQy?3tIxYl@fRfZT%Tac?bHE-eZ3)v?OE|7_Fq6!mGSe{57M&1>QMm|Ed{SY)b+N!+qaZO=|W$@;KUFF5kB$h3`e;dfE&9z3n z{aUnQxpwG9vnZe25BJD!nOEjDds~{y^PF1~HfJ{9sn6?tW2=%YWScmbJ7iCk)wR2t zYgMCOevMh!b$#Wb)ekG@u3EOTXvXptued_FXL~L64Gr>>zIq`q%5l55^p-PK$J^9D zHn&MVeAa(C_`=k};*~Lxcc(0yWpY(6SD^aaxjZxF9kS=%In>V=d2?RpWbV3I^OmJA z*_8E*rB+DWUUjNr{amO2H`i>swE4-j`6bai+oMlQt-r9yL^rS0|MH}VnX9DR9xV;t zvgY`6zsc*bUcK<5*!N=5k2=@YkBTe9e@!u2`)OyE`JoG@=Pti5Uixy`wN1CGs$6qJ zk7m3r^Z(h`^+|T>KBM`wmd$S8K7G24|1r_1>C3*(U#6;mk?s94ldJxhm(?fgFENi> zy*eVOF7AF{V7TV|sijl9S7z?{GxPkUHqG-t)8{RIIw|eViku%>D|;7Q4c+6zXm0xZ z$|cpOnOT*I&oX_cR^@wMPK&=;8dRH_dFxWm+^X4^OI~xAYzP(PTAq3PgGlc8cOIAh zHlB~Y7xv}Sm1n`rUTn)=d-Z6mhEvD-U-h?CEB1BWTeLm(*50FbKYr%MDbAni^2761 z$2SF=Iu6YWiI}?{H|$i>>`enXGOZg-Bwb9}4XQ=1SZ7L@)|<;NH@NGnT*6dZFSNCW zE3?Y{l3`DV+l$IGHLY%$vyQ#swPKbQ`Xak)`aW;5T7K<){Va8}kG+)bIy{SI{o?9M z;mCR!h1uH!y0%|tdC%0;@uyO(a#L&FG`n6?t}XZd&tFWRkjVMs2WNtt<(GL&&o6r3 z_)X>87n{%oJxBZ2IMr{TczbJcn-)YmQv zia4X^aE|Ay{)wZLUO(F3 zvXxg?be(tSJ8*~Jo?9Yo-m<%gc{6Vv&d59dp6}1MN7wt}kBhwBeZ$oEcl%y;spT&o zm_|OUONdQp{A9yYf9miSu^VbkG3*DkH@-fvn95RbTr0|WGGW5(i0}=&Tx!aS0$#YX zzxi(B;J#t`&(fmUPjXo;zL{2kWHL8t>sRDy9X|LEX7<9Kuw$zF2 zl54J(Z&wx1(A;p9pSz6tZ<>Fvt);;2$;=yVO%MFWb)yqz4vxsDq-R|zTZtcn`Xy$8&f@DYq?9b!lyL zo6^SwZ@%qa@HTUoUv|SB?Kw3Ee{S2%7Ljd|{^_aGrtBw4ddaVzRMrYI?qRtd?{v17 zwV={cKiKT~n)^DNCB^k3{$ziuTgW)6&UU({=n?xRYMJjnefBx#Tb0#Gd$}ad`_Omj zklyo+=$RROtc z-S@tpS~Wkyb?J>9r;EpaJ7n+8zZkaG-S)Now_w-W{512McXc!k=b!&~uKe%4-}}D* z_C5Fa`NDR_HHYkS$SPl(M9^3E zH{DZs+*={Me$P&s?~inSeuT~2w^k-_&t4hBJqm>jQNgPbi4lQU zB`!=hf7zzCVZq}KRW7|R!djk7v!0r%wru$vv%6vuQ)b`%m2m5#?&j-e%VzkT?fg=< zUHEdUkJ#2T&Q&(Kt9{f1ZYSRS=y4}3xlK%R!F0O4((V zk8QKOGEMeoO`E(XW0~`BPoa9(m5Y{bv)Iw~ZsJzH%!`Sf^Gj0w*T<-2Sl;}(M8&5} z=%l91&m6H1*-KrWbW`Fq=T*6DIsG;JR%UJtnQfXRHBCzS7~`QRFWV(s zMU#CC*QB(UxfpZwm;B)Jw|Xl*k#CXe!O+%q*3-`HT)(TMEO?>yHi7qldRMo zPIo=DTxHIr4-Apksa0NwG8<19pDR(`Rs3OtSnA!+RbO_jw91@)C3mjpgmi{fcaz-P zvtGJHo$Oq*uEn;ff9kfyvz{-B$(c2y$6@o`9;vXd1y@#DI*0ijS}tnSVaR&BaB`FH zjWr3}=I0Oha&1eR-4wP(^F|}j$y4D=6J&PRvrH3lE{TpZPnxwhfhk?Yre(9pb+zn> zgXtCfnCFLnFi;b%>6?B2^DXfYuB`Egri<3F#!vlV${K&%lJ))pb5)x~527nV4sJKp zd}z(JulqeG%dAPO-fH}?t8;LB%HXhTb>u^S)ju8w`)9sZ|FN=VzUB|hx`hvH>Q+7o zukbne_(%QLru!TI-B|6t9zKl}sxpTL8Ye@t$&f2{8k z!!)C1MVNN(kyXB@SNhG~{`zE=*Mh9$i~LMDTXvb6rq0w=`MSR5!TyKux#k^Oa^O60HI*&Wy__ zH_?ijHuv+S?7(@`r^Ur+E;P%^UiJ9dx&v*Krfy5=of9~}#xzFd`Ek?q>8F-|`{b~w za{8z8>ETPo$V?koijz|>g?L@s{mdUE6FBV04hKJUi3lDf`_$*-N=B(L~xrcMIxGjI0 zSl$ag6KyqZX=Qiv%=S0)k~Q5IufDVVX4ya1jop6FF8nkxotXYL>)M{mbF;V=H?C;m za|)W2&i1gfP;*H@L$jfthRB&z)hqt@!-ejL?%n3Mz0mg|^TKUEa;I2do0VRgQU6k+ zJmTXH?rTg1>H0Hn9+2I)!l0`q@#u2j=+nz`XYI~>YuTQ&$7Am7vIq?`(>=RRB)1-T zsL-PEUGx6;h%cLTyiV72tg9~D+&v@RPR{99$ivmEPToH+>au8J+m(>%WmB?d-!Iuc zhtYfkV{frx!h({YdZDs=t0w)IJ5_z@Y|Hhk`faJ-Rc}n{|KY7!X~`-baq!sx-;!^; z7BQDj(lPbp46}<}^6ZuCKIJ{y%e|!^s)k&i?#F$?jzwGRhbBwFe%0HTn@_xb>HFl{ z7oDQ&D)Woxi~8%VKh!+RTYiz@ltN&AZ0uhNm)OG+r(Q`Nf3TYS_wfhox!I2itl(xp zF0e+r{R=~V;IxNnSp<+zq4T$k67R3-P6NrC1cFGzJ8Sq>02~Yj77gnx?8QFGW{@% zSih1>?A4W*Bb@$Sp(u6H-IS#V zNlf8sp4#h`nvU_TQ(MHdYVX;T30XUIMg^t*6x$LEo%$^^R|?g z*}A=})i$&}+PLlf+&Na=rGIU9CCQlkICV5DDNg!g_`ck*)O=mx|MtMjvdpBvh6?0iGP2<5c%ft zjx!jQ=I5;j*a`-eUCCrr$Y}|b*2eS z6{u!g+pcQzmz(`xFGrxGvY9=nRmjGvm-OB(l~u}NZT%y`6n_KNwp)tR zXcZ2VMmd+`Ev7xKw>};MX7fwByXOni99v9Jyb7Ix|9FCfsHj zH~XE!+w*RS?K{7Ei<0n~g37&FZ@1Vik6RjAwWI4`P3ZUNJEhzCT5H!_+Vx>u%)8%* z(r=uJ3weHucYPMC+8Tbje6!Z{)+w!VQdci-llmQ!vgXZ|qp!Z7{f-Avom8Sk5UGFCaIMYr>X$}DSo_(Sxe zC41kE^p3RR_Yy(Yx_R>XpVMwkIT)(Wz51w6*?-Ro zHEiEQOxu?Pc$o-PA}0<;0m4x4R@Coz516 z96k>P?L>E`q{#v*5=^Q(yjNa%f11>DM(F+?L(bSOYel!NT^p5kF>Gz@i>9?JR5G+~ z-HM8yo|T)ucK2QJ-L<#s>X!Qcf4*<#NtH^DAHRRJ{=T>S`<>$RpX{H{tA5`8f9HD% zLEVS@*)!|)pL+)@oRz%fGjUmg%&e7{L{2{6qA<0{_g4M_yvWY4c^Tq;?px@cspzSD zbT3sDPBLqJcnWZ)aN@L z>)5Ze>|fae#Tzf!t%26-qMeGz4vw3i?h6}sq>#;_Ni4WUS!GH zL$%7%jCoW0%`(HX?#L~9n^T{4NAQW?yGd$7OXglGE}T$StZ|_FiR9F@)CtKl`~^xU z?$(^N*k+-rb(7KW_I{0MLCr9B73GyVwnu1~on{mAonhuiC2XSUhCGR})Ctq)Y5 zX)@VoVd>Y`+1t$Xb{E7tf8Ms1ckAu#ra5`L3cSy51@< zUWG~G7UQ#J$~h6!<)(-3;@!QPP3c(F;zO17>u$H`?lhTUa`#Pc_p(V7z0ZD~xFYiM zwKTQKvwLP^}*Gi+zphRcAL~4}*BqX9p!25gia+Tkkg8**$r!#=Yw={#Yzk8~M23 z(0A{ZElRSrJH_tI@?eO3-d}&IYR#o}6`qev;_~vEI9zuoM5L?TUgNR-adLk3k)~~v zW&cU^hnc!fk!<37&D$x#V_uqa;7e(GlbTJ|qgfM^*2k{>c)b0pPy2cyZOwDBaYkVq zCu{YcxR%s+`2ow~vwo6+tWyh5x}3@~4t3};uikyu>~>DLa^s3-&lOT-$Aj0^zp``W z_E3K-=eg>la>NqLOOobqrnDXvpWAX>BAY?O^YXg)tlx4BABbJXO{HmSaz#iv5R|d9F(54WEf=D`xIA z6YaE`v!U~nWHM*U5g9?g*_#7*TfMF~U0ko&r@A)8yl0-b(Lu(bSS2yzM;-REE}Yu3 zrBdH)RwL zPD=kcwNJv{mR zw3F{`T2C&Yo%y+HI^X(DUSW~7w>(bpF8`Pr)-67F+pZb1Ibo9bIy-$>_XV6Nsp^rt z{<8c_^<23H?4?yR<1W6e{<6U@{DOPQFM-;K<#kdQUP|rbo2u-MJ?CP zoPW&x#UIUk>pw65>DF6suPo1Avad7$+Rx23##tw}JN!;c{AM{f|6%k(r*&-|-=FcC zPSvO>+1G2|zu>&=S{EYZpcQtzqyETYw>|tR zV%x5_EZN-p@Yk0(>21Of`BFY@xY?a+c}qNQ&eGS>9a_l|JI<~ZUmX2>_fNUG{RR8a zG1stPW>pta+FK^%t#WANcJ;<{?my#t-(Rkru>a_mk58n!U-Nj+NGs*veTM1z@1HaL z<}bfpTGt?d<>ze!&GNSsHmP4)R#a_qvHqc%>7B#_JKq*}JwEzTtl{=lwX`p-yL-IP z7Oc)Zc6giM>uE{~cZ4_Y785&u_2q%C*0*|x-ICkHcU=3&edul&lknSp247xG-YU}( zwoGxCfh}Ki+fpVj_elY_grUjKD&yUwjJpA3lP`9c&^|(mU%{_As z=hh$b=UTjc$qEKac2|C0|06xO{`7ul&sR}`FTbS!+k38F!2RFE z|5G-8n6b(C`E`}AetFGF+0$hY?zwhqGcM23nxYUJuA3%EmgH@&g1*_MhvR}EPdC9l68&uuFds2sIl>CrN-)eA6UHwN^ZWMs(r6)q1mOZ7nSSQaSPVO ze%QKuTS#6{(A~Ffx?9DqWKR6NwWw32>d)Jk9UrDmIaM0;?}X0Eb@s<^ck&+I?$D~r zyH4WMW1Fj)<(fICXC+x%a-G*$DeXOfuf-~hjb(XH7_BExbnaGpoqX5KZ|y(6t;#DV zUzSMQeLSlEM(CfMv-={lz7@wDwfg#buDRq*?$=chP8y1x{&iFLO|~$nv|>U@zLVm$ z9O-Ggax+w(#x0)MwOC_=nbeD!Z|k&;WmF?;r!6@@W$_9BSn>UpoUa5=7OLuPo6^nm z{NJIIex_?rx|pQS7J9#U*^^`4H(#gxDJ;s|dT(dfDR!3QD+KF3*PXtyZNu`5d@gfK zKUF*H7)l_fn>Y2H=LLR))ZX=R_yRIEJHI%CNR-Gu$`VuawCD{4%O%ilxm<;V+&_U)78@Rtc~C zbY=F5r;hJSOKhuLW-S&`;XS|g>0gsf;aMkrQ@>wu+4Cg4+WB6c){1W@ANOS0|59)H z(`>SIsm>GrpIWE1*;j0szs%0VwY+cAW)Z7tjm4}fYnMoF5tyVORFqc`cKX!LX?Y9$ z9hKzQF8W*lC9{C@lF=@~Z(kGgBx~F9+R}^{JWqdFykM5M@k_BiKVOEO`Ihu7cSiH$ z9gF$z_wHkG`zG#V?X}Ri*<|n1nuau!%CL&h>X)}OUESxDe{ZeHW}_#sm(SGR(|Rwu z?O&AOr%JAcPu4U$?_c$1`Av4u_1{i=pZM?KYCkvft?ZJ5(+u@zSAMGu`@#KJ@%_fz znSpk^t$SMkEtR+MDqg*H!ZrW&%KXJ274JWB{cDn+enLI=sP*~}pARlnPucmi-06g8 ziP>Ck#`8<1zJAfz{C0uU7TJK+!XknW&y#jk@Xz%OjB+rPFzTxmTf0ytEi$D4Ih$9Y z@Yf4|ua<_rTAatQrT-qcL;XJa4X;}}^~2TPH+XV0OxC|3o;XLKqONlvPjK1ezY08S zFX~14#UEU;Bd`9N>F<}T4NMMk*~TwkuYGg<66X^3l)OcsUr0ZAbo5pB%h@IBKR6?% zPc&oMR@eJ2D`d&VSgE^brS3X^Q9B#A{^G;~^&0Z`rCNVloV~u{o$oAzLsS2n)K6%8 zCQ$Lq<)2Z-h3g@e`nm~L4#8Yrd%g!}b}wJ_Q)8;^(ofcgL5*jMwcE7Z`77ToZLMVK z;F{GRboIOAmJE@JJUaV=Pb%!2;s5wT9ZOX_XYY5#2kY1b)-Sv&VaqRem!~?WMPOIh z%hf7pZmn@XIOXc?z#C@#F?x%tU)tSxV-rzdC$Ko~m)Nn=)JVzQ^2tfNJ)c^SGo>e-RBr}Q|J@#g`4~`=N_HESZP0P_rzn$FP0s+pt#F(VVdT=bY|nN z2Tp9&N~!<*gYVMzh4cBZXuq_snEWMp`c`LI+a*Cu_IU1iwsQOXRU7QqOw#zz%~Ndp zN6vOmY0bQ@hrP{PxB|mGDBXMJ^$abN&-Iqoh_Xp(OuzX3 zrJx4G$xU5(KGrr3Gao(Mv!;0Nyx$jR%h(4y4Rrc=sOdI+CP`d zEz$*dJMX^W?D6~{+Wb#*%{AA}4yBUUV!WbXW(HJmy!Z1<@Gr@lV&07T3+FG+x3~Gt zW4rpmzW_02{*@ct9JzV^IyLSUSW#84$NjB}i=}Ntp2FkgKUXtDR$u%qm3w7Ezzd7B zZu1!q&h~b3+9IoBt=@9*8*7zetV_v5@1(4%#=*Q+2}Y-?d1^vWPQKTE8QOnHVAA`r zY4xiOqC4E5tDV0UDSCtN`4mluurpCiE_@Thw_Tfk;<;r>E4$(kA&=?2-6r8jzk6@^ zb2{RO=#guyKOEJcm{#Aq_MK>yQ~e3I1j7|^M`wsLoeRD_g}wM$^QY@xjZ-7-*DSfO zVc)?deByKdtQ8mYE3eH?n54d6e5rTK@(nv&E`4pjQm=Z{@rdK6qni%DnJBB)G+l$a z%uqe;5&H^{DXS;+vs`(-Jg?=@<>nI3M<=o*4b2=*GHwdgZQXNeD%Vf;7eSpX=QW!g z>|8f*!nXql7y6%EwD*!^K>k98PaCJ}9XOZoXw{wbmFJLpkk7lrdRz3f52!WtzR;KW zEA6}NzvH?(*<(N1>wCWYTebh2e$Vkg)AIV}>jJ6~J9q{8gumFS%sG9-Ief$PZx1VV z=Uw0EFIlbq#;E@u>*fD~V!Ii3U!DKLw4%l+tH(ZB*R$q&dT*`mU(>ypWBDanzFdEJ zdLg%x!hgP%drpb6W&U4wQfhCXg|%O()X}yHVOwS9oaWeNTGbq&BU4#F`Pft5gRl4L zbaDksN;N&NS)7*CdB$#&Y|IyOZbNtto9kkl1^&@=f8)H}+dk z#yOmx88g=}qAv8z&huqLlk8Vdy?>Fb=Ff+{-16@iUVb9{pfJ-ozp+$Bmn|V}PO?pV zV63I(@>LGgf*Iz_*`&r`ZJp}d(5!X&c~p%}!sBP>Y`&-7yES+I=|c4lhlDE@%{II- z_d92gW2J-Xi^kXAwa-)+6y5NC@BGG3@%eqmdCjNt@6>OO_S((F<>j?ry_b=J;XTu2 z1z-F6z}sGj9RzG=FX>(TQS5y=t9+Iy^HFox31W^KS{hCJa&Irq>-D_3tgC)$f?&-D z=06&RWzk1gDeOCQX68)e;%~#ylFA!|JykqUEMcjY(sYcIw zuGs9#&s<=;BoijF|-M3EVKhL!LFAki_FH5kOT9ux`7wNgpaZ5Ij@)3d5uw5pHk{dd| zRHP~Gy|C!U@rrz3hq&uOKh-1n=O4bTw(^X_`r8+zPZ)gEzWL8@-~U#voWx5vGcI4t=Oq>9>)>@8Jk6SwFFr&(FR z9ETLoZL=7BXU~{&!>IGXrr7)|oC$81T;{pVGTf|Emg${&+3EYVb(t@n!gqCxEfLwi z<@x%|`*y{D?2_||?*l^BT%)3m2@BDSujvWVY&$h|w{IR2@xgzY4`Ug+W`AMyT zHsZ&YtJ?IR_c-xzv(8D6Lgn@ybBIrW zDXkR8^?0^Uopw)t`$t*M`$xaeII`AYpZqcYA0KoD^|>t!lAlbi4~p8H6MWioTiOez zCq3&{KMV2PsB=}Q;K!juKfj#$a_iHhFNba&-TCIrtw)!f(!Mn{oH!Hubk`&;%__sK z9t>3<*EFotbl#rhx;=c#q{Un>=EcvbE~&~|S+{C;hF0sOT{$bCxh_5o_=kBw2&%U(dW)QhH7Ec}TJ6$*CdR&OZqk34XkFzvPDNrb)I& z$uo{lN!Kbp9Aah`Vr;tp#_Q)NR~u!{N_pXsvp#d%wcwDqdp|~WZ#`6XXZFe4+EEt` zMX%Xf|5_K;zhC)*%;rCNB8<9;QBooT=QO8Ttu9bF%-Zzzh~H&{6TFwBJO8k+t$A5L zX`5n#-nVma_VU|Dr^J<t&6g5GPT*NdY`pk zmX^PC)9(Lje-rXfKYNw4+eXttLH>97LcjcHS9$I26i=Hviizc_*6Xg$`O$hQc~$D; zT~>QDSMPe-X1iebMIj9A=HSGw-j9?p;*-z^lb9 zXfL85_)bOjtnY~v{}{7kIvAeM;M0@pn;Bj?xvSnkviCEmq;Q4DG08ciAC)CD|3n;{ zT;X+0>shKzm(Ja{cTX7AHHD`<30x3;?@ZFAi(af(r+f^)_EWOX&(ZVb57zZ+AG{^^ zC%p{aqx9fP{cruMV?VZb+&}R{w@&@hccW(p{^EAC>jI9*r~DBVm0bVO-{@b@b=EIC z-<)chIqOQ737H;rqVDX8-QX_wUv#d1ZDLoeb#Mm7y7aB{f*MV9D3B`7S>9_Nv|ae|hJg zb(0GBPpDi}Q}mzV?d@NO?%3~nC*ILp^q<>On)RsKj)XU#RCbGL{kZ0|v1j{b`O{l` z682n8U$AlWmOLr*9r3#aUoSCdoT$HIc5%4GCf4##`wtftS^Itu(7Aj|uU_d-Qegf3 z!YPxkwmc90e)FPtHFwSFO;3cO{KZ#wvsh;}f0Syu9&@$-g2qK29_0q*iWw?5gAY~uTsp%L zY=lXfu`i}@*P7=!W`8^|lvg*WVvp>3s zzBOgp^f86^;LRTqi`p*CJYaSt^q+Q&^Kr8!SEZ~nRl_fezFd~5;NUE3Yx-p#=erkj zHx^6ZT>RSW-r+Un1hAW{TPp@;-w|;XUKDRhcV9b zKhl}-JNHX?;fl7yn|b4HekIHO^$OBluPrSDD`muPe z`3F{)^!fL>zuVQ@s3R#e$9K}!-P;YfNGSvzHkEm48+X)p>Kn8AzIASH8sW#^?Kt7C z`7-cOcFTL4-pMaiwpVLDRG#uFIc4roTL(psi=Y25j!^hLS7ec^&c&O_D*DMszozXu zS0~fI`;EO@5r>nXigoTEwhxiu}}T9ar&MffgHH-?%yx} zMYnr&S6t8y{&nC|Zxw^=f9B13Ve6H-R7BINy_p#p_H$15&la8RFiB{#UzKvbrtJpZ zfB=E_9ij_$x3CIsXmFa^EyCsK`QiSy*w;=sRd2i2u+Bdee!!*KE9uYjk28A;&*e2H zMQ@W3`akFNnK}9UEUk^J>;C=wBziz0OvOa`l81AM6StC3lEjxJj_($2mhZUFu3+gi z>|>XCEVO6F6orS1$Cdju+4_Ha>9Q>1slV%a_k?Rv+nlr76Mf=(Rlcm%jXbRu>Ki$& zw<+n!$*P#EA;pstw_U&aC!gDUj_$_p?`sWr2v>zAW(YPdox65RlFj7Hm6Nupe(jkP zKbbf5O}Eqb1*Z!NUoBlJVZ18PAiVsNs|VZtJGx;=E zc(7bOr}N}>YiDgrT(-?O^ty!*&)RRd%3QrBZ;1P%X8z=Qk&1ry&J(LLS48Q>>AfsY zi)-_hd6lB9uD6b-f8U(Eo5Cw6T?lf$nR)--HbKTo)6YCxv?sTgtM53^?B|nM&uu)m z#;0&^XP2T{n`4`U?sJJHp|!_PXc({ZnBQkKo3Sw5ZcF{cCjPoDMK&K3**41*+nsr= z={)`NRf8T&p~`i+S-;kWDau=|URkrFE4%52lIo_#&8=D=WUq?+HC3B2*C8ZoX|!Xu zCy!>^!}?Vlqmnk+`n^5XR%Em+tLxxqao(r-^UiFhBbn1!?^}zVENUuyVp^MXa)buVZZ(|964E)*9x*X9}BHxxYkwwi|?ewy2<9! zUuE|y+%fTIu|M#Y^WBH^E4x4N&RhELeTFqdJpaUHiYLBZ+)>Vu`Iq6|*MJ$@_Wg5q zy*$q~>_UccLXP0t9L~2otqjo{SFq%&yN9S1aNl)tT$6YClq+Mq-~rh~FBLPHZ|JjF z*wi)Nj8>VgwD!QmurF^cs`?v}jD1ws{g|lTXUCL&O)KN5ewbpB`n&D-4@n$IowfXA zuCeWAE6<|lXS4G-%UN6YH~JkhVEVYPOOfy6jV{5`k4D{zx85FNI_tUp3p=PaJNeE< zsm)hvA2V_Gbo&bbVP;?`oqV9dt-k1Xh`_(TwNG|zx@5J?Q(EBx+j7sE&f@IZH!{5^ z#dS)H-(j0mG+FfOij7PAbT02>>OT-YMRJCS(S?7_4`nMvB))m%C0+M>VlemN`JHcW zZvOptx$Ww|pXbNdF&nhE8~G)FWa0HTYTIyP;$+3dNH?+Rhj%osmXYr|%XNHJz-~3? z`eUVi(u#MU>`;AdW;e;Op|o#LkA|5AmrS|juetd>RW)siI{7!J`Wy}0zPie7wbV@0 z)nUPB-|k6#RUW!~-EGTDab`Y;cOEJzz7+qrlsA0O-9^)9-%6QqZB6dnhf@S{OtMn% z?pr=>wMyqRUEj5NtF|eA^IfR&z=&t z)>NO18+kWRdOgMGr}O&_z7kEVVg;|1-dLQUzVnyMr0pO0GNLnXr&X2i$*B|zVSF{*~1wUZ>Yjwz9A`G%Jgo@I{T|%(&Xl3&+0KPR;iCw-8*A?!^X~! zzmAwVKT(L}e(JvKSwYQO2iM4oD-wD?+qTqsI2^vq-x8}OCjLLV@CECH=S5FDvtGY# z;Ip1#{V#jD`?LA$+|~M)AK7p(*!9)dz>}+%z5H5LQ`jbVy@vmN<*CnC3wpBJx*9cj za+y|TiQY}LxX*R@^px=OXjgWQ`e`gpAL9ga3I*mrG%MTx`q(LH4coP>yTkpI*DEh9 z@>>}h+&OKjo`t;3*(-G~HwW(?^vA1NUT# zx;R`ZGT7t0J9-QMr8O#(>=h??EGrZI)A)^XkMm>C!eh@a9v2fx6aS!hvh8Kh7elZ5 zZ4cM2m^P{BA@iL4sK4AYwI-{pCwQF{x$S!2?U6gnyv6okjVl=R1y6Y?UwS{|>k;*R z?j`(1nx3}{n!Zd;ua?ko_4nHUC`5CHo}GJ&c(eXD0o|qUOTwe_ZHt+O0`4nMPw-|j z?hc%GSR&f3E7q+qcImc)tF8MUG~Q}om&7!gr9N`avJ6p&8FfLNOHMq~Sf|*VndN1i zH=%L=#K#jXoR%vqFs094DCQBqXy)!a8=2qzYE3kIZsk{@^}Ek<>w)x`<1(N1s*|=h zaKF30^Tn+lE#EWaTs!t9OgqG_;P-il%C9FnldkZc=LnuC;4*&?+eOy&LiR=T&pk@k zY|zj67c}WVBkN|C*8NPpHE)8>U0`EiP!nWeu$_FdR%P;+cA5IK5iiSyLq-1YH9NcH zGNboIE!RSq7n4dFo2?x-$iEcf2w?xtxr zMcCzWsW!KhIoo<%Z|E#$ivBUBD`5kZnvR>)q`>a#pO>dSIJM$f z0gJLx(haR->35H3|4zNr!!GghActJiiEmtYn%XNXT@Ed-`704`AJ?e9A@qX?myqwyEUmPP|kf{YZ21 z(!)|RSI)RhPkd#bxoz?7ZuLv?ngZWcIdrUeSNc2O5dA2#fuU1f$*^&P$0?cc;!@7@ z!durn=`*v;>V9p-I6qYOT2SV;O`Ebeo2}WpBv$$ArBn;OyHmeQc?K6>HZzQ~d0Msf z|J+MwQoIw&r8h@s&S<->Rzf5jFc+VhF#LiO``c>+(lws{!waWjW9&w4Nsh&SM?Pi|(<>p;4xniQ{ zzrWWuv(0Q#>d(-pn}uh%c6`*mdn+K}Zcblo+HTulVbendBckk+XKtRntGfBw6CKU9 z`8y69*Y|0(2U%6GJmYP7D(1B8g|}NBS86!NSs2f+d^uVCt%A179)-mA7ID_P-~XS- z6uwD~i<_1cd+M}NTvTP`xzk+h4rdl9w11Dvv|bmVUy!i+bHOZ2S&^8|se9gt%$U9U zUD@qx+X_2BU-jnFJDSS1C?o7b(^9T!3qubU#VmT@wnnhNV{X)3AE7n3q^>uw(Boe> zJE&y+uh^iq(T}dIrH z3G7(1V*761;|pUxeQvGy;fp%Br>WptrF`MrjptkfS$}_A*0Nn>Pj9)%p6T-o3W`>>mZYfDek%{{`*lJt^HEBT{pS@4v`=&mS=kx?wh4 zd=EDqSekxAm^Es7#J7qK3}!w^3~k4TXX8AejMeF zT97BT_UwC^D+QUn!E4w}U+teRK11d8?qy;kywjPOlj0U?9yt@dYi0?%P2}7wpVjyC zaI8@k3SMEHlpz*!u_MEO>6(derYxAKC3#M3-TlkUrsgj{@GJBCPvgwJqER;Mtj|44 z)t(l_|8B-hAI%phSGqk-<*?m$B6FtA&fWD5kGs#W+LKtjYN98<JE+NXG?z~+vLXCJ=uJTmi+8r!9YXCJDYTxQ)XE30*`i`sBmxbx0pN5ze+ zbG2=^oO@t0+qkoO{W+G+YK$F6uCcFun6p&ZGWLeizgNv(`z@qi9QTo2RdM9v%C6;e zwqIWGxvYLx={>(YPkUs-Z+sx3^=tK%3+6Mf z#!LMbdU$WW!EcRozx2%7PM!HW=TElP^rOcDLz_yEWV};+6!9uD(D`0Nh4>^3hgtjk zqY4FbA32wF_1kc-s(l&BUA2Mh`sBRTFJ+ugvU0zyVYXto{zJ8ej%k^HEr|HN5vuC&H+co=Or9X7vYF|`;cpD!ORq8=qi<%9gJ^W!p}+!i?Kw;|s>(A+Wf{>0~EB`V$A^-m++g0gqjY-0T~ zPwH^xy+r314#!xZr#EfdP!MqJS>+Ao2x~U_# ze9ozdb7vo1{Wh_cW9z#I`|B@lw0V9dY?I6*i)UT=0>bx$L+TIMK63Brn7_gMPfy@S z?!A-h4i|p3t`n+%5MFrbbNG~+P2Hci&3+Wq_4vt7xlp4-`>EST^Kxpm0O^1 z?i2OvXVnAs9!}dISS-|4Zn0k|Bx5_?8KKRdfC^7(V#(4NPXYZqqr zH06$%NN>-+1sN%8xVzkry^Xv0VWoWegdU+a-+$ceR6Ea`c;vx?iSNQM)D?F8UsZ6y z@BZF1`;44C-zo6^Ge2^0v*J(t%_99X#8?Ct+p=%ouvAP)^snAGTe-P==I-d(e|+=) zIe$gp>~}o5`S$jM0=%dv->y7iG1=gxgiI##IjIZ?u%uC$dGbVM(aC;{Qj@!G2u!YI z6X1bKFKO)M087@hb51rqDK3L@Rv=6j0|Ud7#sW^5Lgb?ZC$BsuAcJz+7m6k>KBy+e z$+J!h$e^5HgrcxR5UP-4^0L!nlYgF+Vp^pL7y2wA2C`^!#3?DJSxR8x+mZ^CSDw;h zTBtdBqO$bl52x&yQgtRzRMwdsb6Sfj#0;!x?rC`$l#P%mcG{VP71itUPyTaSKn8iE zf-Z`}EA~)@96X*#+ZHB2JRv57vP>LB*K8-KF80YTXAGEX!ol2LFCLIrWDqkh3=9@1 z`ZS`z3hmDFPImK^nEdyQfDFozKZ;`R7^q@frnY1-bAFiYjqp5tTkDV-dUp*@-7ycW~c(#a<0t(lILPA)tj%j91% zx$wN?5*NdqH6Gz+jEycJ+3!BEKrB$FZKVtQRIfzn;c)^WtRx8>vidE>C`QOc4}U0;(ux e{kuHb?zp;GfHx}}NZgFUjNz3K1B3Gw5Dx(LgbPdn delta 19998 zcmX?nj`_eQ<_+46ysK`e-C$;AV0gvJz@R&MVY1j{KSq&yz2uz4;^N-0=y2h1k$-(N zQxarYlO3A7n$3muI=5a6+pxuJuL7ekV~)#hzLSbQercCZ9`SxJUj3JS-?ydyv8!u2 zx2(H$_4>c=f8BPO-)Ek55NcYjb8V*a?>D!nd)5LjdyS4qO-+nGrz*UU zxw7uvvE+f#I*l2JLhCpBXmcnoPGH-dwDVfyYo||T?9WnCQhPLB9NN>v%9_4WS+x+1>qUSsOUv)UFdO+4oWEYl;}tPcu!sfbH1@!aij zXo~jUArC^rO#1}5sYq2?p%6C_V2uTW~HlVoZHoxD0;lMGjX}Tq?-Kq zPZ#GZx!$<#Hq-H=bKFMnDW~71CAazg|FY^`z_-fVML(I#FI~}|+Ot;Ng7fjd)}wd7 z9Ew@?&_iOnMz;Tv4a*g`sS7PU`je-;KKw0{b9{5t;c%aM<(L0SW_~jh{=PwGf_Qdm zbzVl(mvX`IpSz8#ZU#@@=yXue?!@O!**C&m-6pQuoD|X86Swu#>N_7ld{vKHk*(?+ zW!SPgv}oGa)qeB1EdwvC^U_RQ{fMJ)l|}n?$#1!bg`00xEIM>RR)-HQgT(j_zca3Yt-z9F% zOWcB;w|5Ag`aiL2{YT!b)y8jPt`_wQ-PaH}eAIJymRP;X=`z#FTJMX_#y*|J@55b_ z6@LDFW}9dSH`~<%5$m}4Z$0>UD#7dM_8)#rzS$mr@PAJ%&+qN8op(9TcIQ1=rn}Y5 z>&8~`XUjTnxorAa<!t0{CdQKvp5ai+O|DmEb9c@@v)(F3ovZBW>b?SzJ;!Gq`V};>rgit^++(isk60gC z`QEzz{OHFc*Alm~Cdftw%rn1zLnn8m=e~>!EuOJPq@bR!tKenbK);2+c?}$`zX#NtUTdb@|S7L)EB2$WbnQTzxC!oVU+T` z0(-v;tA24wxHQeXvQ|P#*C>s7iTdOo{@yi-$KMFI6kU>^P_*!()FD%sO|K_pzld;t zK4S}?s@~NN#(J(-rOJ9+A3uDNcj?`!`qo8vZ%TdZaeXA{)|8=V;`6>b|H#t)0@XTa z>YVwTJ^VgRvTpQ?`mOPU@lc__;V&2Md+TBjCF(dF&OH>hKzQOGQTu~cpOVab1o;Jy zYXq^VIPI6dw1s=(QPw#}yhWaxtX=-Ws8P($|FP&LtKj8_?5n4qi&OTrzfsJkc3NV> zMcw+v*MIY$d@xRCcc;*oc=fcl$O)^m+CLh^16Rtn^@2LapuJ3!V8Uq z`b%E8%gDW)=*KxJ>qWQRiiZ!9T^>D*m-BqH{P};Ig9~G}*gwdUZNI+Y@5`xS7cP6R zaH|kfv&jpwGmW)UIAKWG1Pif*cas8f{ z{_I}yIotBQXV>4qw`aU_Jegg1M(Km3YsX@^KJ(=zDYhOJnRe#ewC2=1WfL0mlaC&g zZTpy>DD&z$4`;po{-YCgPR~l%5y6@Kao676%2%ZK2?rioeL|~$+YYX?JLP>|x!qWF zr)^U8-L2d5IwIOb*DXydh(ES5;AzM9s3wD>T_Il=tgFx!a&-Tg7QEs?>zgAJpKM*a znMt*6<*p0TF7G`;rBAdPrA2)CJoWn@X8xpw%?}q$>fO!5{qMw~)vEQEw{8tjnPJU- z;z7=-ZL7MzUidQ4&QG+5Up&)i(lN_<5^B;>=G?xQ-`}1VVD@gOhQb2xKeH{K868mR zHVccL^^Q6C$--WDp4R`necIl1ZVc|6InmcRrRqq>@vjM+Z(mB9o_OettEbZ|y~CU0 zB^xqCk9`gLm(%g^q`(9FAmio9DfLdLi<(!PF148H@$2VXBj-Gi&bOOpe)!U1X6V2E zSnE%r4QCV_^&9*c*P1Z*td%+N%S)PD@>l=&Ciz0nG&@@co0z4hojOIepR~JX#k^w| zdcWt1;;}u2=j~ixN$bfR_*ta%T#)yM`c40me?CILnJ?{B&SY9&`bw4D^oI{-HKqpDGX!`uvv4smaBwg%FgP-pZnK$v zfRBM;j_l+Gg6j2iBROkgjz|8lzw~b3@~f90e%-lmli!<&Ynj%4vZp(Rz4xV@p0sA_ zlT&4nY&`uh-C7;{^lkKQFE3{=-leK7i%rg6T;g!sLG!_uucvx%sj<9rXeBluJw2wZ<7CPcK);7|BW~Qyt6&-7f-|7PuCQ#J-%Mw^x|Op>KnTk z&bl7*`Sq%wyr#b`h4)Jy$$z+=x5lnRp-#Qy{?YfWA9?EHP3sp_{0lIx7dgWBXJezj z#E;1e(;oXbb38oXR3R51aydTe?EKk3x)tvA?+-Z}FZpBBuYaWi=O5-b{fMq{HLVYK z&8*LVB;WMI{mAnKGFfWXk)1R%DA{AJ($$$k`KOGS{UwCBP8CHap7PrITFW_1degBf z^&2#^c_Y(L{ZeR4Y1WkX-Rb&PdZF5;lT)I7cb=Vcc3F<$)3V@gvo0+#yOHLxSkaeh zwf4k}u zGPHQNak3bEA`yQRd>G*fc>^TK$0d}yd8}5ZPS$KKE*osFcy}uPlod!BK`ha+pBG6!XC`xfJ*Jj?Q|ufA$*l(5!Kzx34!uFf}Qo4U-Ns2mfC3QuRZ zjEFI_4_&}IX{Am>m}>CRBh2qKCfi8(F1s7(K2@T)-g^FxwOR7q(?71rlH2@1DfQst zO76_7F-KIn@An^nvCs4T?7X>Q2@6fkpZIx~JyveIrurcB^P}SSqLhBc^2kl$w{&l+ zmq!=%zuEplZ_nXF{*Tjjc80%Gc6j=FiL>}dY!<-L;mtd8L2Gisq9ugTy$%a zaZwn9_q*wg-f{tn8@hzgPb!|V`HADz8(!xHuS$oWm5_e-I^sk^Sp9?Wi{6n&dcsZG z%lW>1FZn9d$+K)m#>B(E!|4) zTbPxTZ94AU@QC`j#qHN4K0{|+@1qfc6H6QuwoHv&aYXg*jl-4`qV{fJv%0i#$GQs+ zVYW}_dUD(M_eTf?hs~SLJ?%(+>(7Ao*R}=a?Ahvkc#0}#;!3vX2iqO?FF2<=b6R`R z&X7H2#fh%DVl`}&B3p}!x)e_cT%R;$L)YJC=Jx0r*E4rU9GV`#YY&eer&3qd&aaqvrCA^S?juTvop) zR?T4LiKR2lce*@CUg@Fq(lzMi%ax#p*Dns_{u)HbFt9QLA$eNd=61+B2gm+W8(>Bu$Yj01=x;?4O zB**jZ<^Q?bucAI}uyNAS41O5P&Rsr}*IV%hUwzoKZ#8$HerW56eb=-6=hObHNj@GT z8^y(o%RQTTe0H7mzUh5^*Q2ifb1F8!ivm}KPqW?S^*O(-+}Ue&nx;U1=3Mi|=QpUH zy%yeBSuM6lwn_82^^2a{FD-=YV=op)99sT;MPO3y^doCtzxv#M_fM<7L207Svt?hl zem3Dg>77+yFJkfheZ^@hv3QfiyifCEver#|rq;#0vFzYHRq-7HYhRVid3`RkdcR_A z>O0G)@2_m#vPEUz>TVz1eeY7=yUbm>J>b^8qtVM&uV3-6%~&=oB7Tz4&fD3yLhqgF z_txi+TvfI0Xi)6ucAt+&H~TO2be#M&^~99*itVdU#eSM{e*fd*`qqmfhgn?n^yBVW zX6_Drdi%(V;G#sU1v^961PM@BWoBkv=bf-J7OaFU|C2rL4a$N9en%HLF%W^}Tz!*nRD;?NzOZ{cf%d zblq8U`%v_!eL2UbAMmR%jDBb2`+t?k(`~mu{nwZ(z94B*J;$B!w6il^v%AV8zif&4 zJonj);}MUNJ~27(-`*pCeoA5P&f^_L5yyL$*A+#Eo^$%jmm6c{&UIpb?K1NcJyGrY zskNWaPdZR>Y3`=ItZGv}hDZt*#oTE5`l9hbW1~Tm#rc1%45A&$y2~bL^h}oV7w?sK z^4KePgMTG^%fDsC@pj5Tcqe@~O1oiq=Ay!%4OTqg0PkMeS79>B`(UO|IZsDelPo-*l z6Yrb;ke@c?IX+&ecZ-kfDybnm<`yON|GwxF@^MjP)HrTCT0yI_*H$gi6^^^8oAi2OG{T`emiF)O+c*rD5yy7xG7Kl)1e% zM|-!P`tP^1!t19^{=rm{VDF%cUl_$-CWtzEc45Jd6A8IDrXSo@_P>4;Tg|B)^Q#$$ z-z8j~_iB}`X=442GYOAByj#`v+^|%3dx}6Mm$rSI@4{%~9l3n7+nuA+3V)woofQ@q zyYc&#HLI@Oe-(OFdqe4}SGMODuKXyxf+zR%f{#3IztACm6#_6B6Pj^;Z~b`+$1huS@-LE?SABlmupzv#Ym@(DZi{C9hdTRu*guHQ zSzIr+{A1~*dj}!~Z4~O}OxC)Ql<2bjK!4Ees69>PkKHA%%&idXH!kG$+IMKD`V2k( zP1ovs>O-geGW%mu?Rct&#lCUAi)rbep6?sNowMT(`(F&3@6}V|wQ;()=C@6np^8^4 zgx)(ZU9sidx)0r*%QGg&tAAg;V%N#uY@Rjd8x9{Zu4kKP`k{{bykx~ahy9Jh0`gDq zr1a_?Rh{)(`o#`UU*>K}&Oq}_-;+Edu{<>o)VSBxUG(`UFL~q665G`8x>_>9e|Jn= zed+O+MOy29i*Fd-nQ_oBv6%gT*~j;O|K2{kKQHo5>DGYljC&tA3G(F}I)7>DXC*t2 zbNmkvTMF)<(R}@HeXsB48@DfilB&^fyER)wySdi?@FmY0^T|6bOU}!D<3IoC-i2C8 znG6+?@(;5e)mInG^>4Z{V~O15lB>=oDO{^Niv<_mvpur6a?ZW@0~7zU%G~T1mq@VU zEPwdi#B5(|a@kSo6=^+TB0V>J)b_pK9H3dq#ar;KaM$Amwst?0cE0-b0+o_2pDw>R z^&rB(_{9#X^4}J6>v-mNOuF$dTkzcXlnb}t@&7(l=l6{#+^qGNk%ed5z3>b5Q?=Qz zoH}@EYU2DUkMq8tP0X+;@nXCY9k;AYt^0vW^DTdG`KRWu7rRxlZMm7!wLWpu_DgH_ z9yvW(XLX&}6&3H7fnt}FbyS|N-(3IYfK<^RrqkOe-PvxKCBIbq+oWIKKT_QaCfS|4 zB$s?;{Ug_Jzc_{Dll>FFJ!Xx!U-$QvHpkO?nfVL)P964LvBUG@R4emHuInLQ?)jf$ zK8kv%WN1xKF_>+=WZp9m)?)XJ8SPg(FJx}BJ!@XTJuxpT;4}84M;@27N zu0I#2n{r00HfY~;#+pgH_V=fL5lMVEbCJ)@zzcQl=ThSmS9~n3T@=kS$zRN9snjQ5 zlkD2xmOq7_6;;(ubP7qjC%^VMVi-WC1|CQxhd zUQCp?|M$Y+vWk@q$L91F=8K7&HLYUgGt!c`xU7#&&e_McIrM|g*FOwb)=yQORx)Fk zdqiz?WbLVKiz8c$wy|=Yn15;FMu`sp?AuN(4d*j%A8PqE{VT8HA+4%bTl?=fd*c)J z9nOVseG-4PWuIGULd^eoU*T8(UHz1Pw0QW^o^RNws4`wi;? z&HLZA`|g*2+giW>gHnTUMYg20vzdG9H{+eBSJ_f!+0W9aLsod%QGz?bDQ!>^o=Po9jA1==x&#cgH-Vxl`u6 z7s!}q6uJ4q*O}`MOr1J2+fT&y@<#WV)vHpZ5^-!}|E!&hR(o4Ep4;;H zS&(J;`6#znEvuh@ZksK|{p(&-;H%@W@ACM+n!PPYR?m-n3+p+ZyXTg+X(rS^Um@^S z?d+jjyiBX5D_?Hso|hLHl(#%{_PxBu-@@LUdV5;jHlK>r{~6F7Sl-9gQax8Ezqaz$ zmfnMpzO+1)yQH2XbL*0k&f;C!rz$HAb^J9Ke7$XUHo9tILP6DAA@#`J6WjSN3oX7f z>%|)Wyfd@Ug*(fiI>o`=7Z&#P7yldUne~RBo^Cj@thD@80rN+(+XkCj?Vh*fT2@W# zdc4Hl(LU?T)yvMG=hWP?$ctDa@Npa4wVnA(FHM=s5qtb2%Pn!aUm^R7KJ-~loy*O? zX|`Hao2{*}>4N9AqOAQ|6+QWXdXR@1{Q-oR0vz)uyyGpi~ zZ*<_TXZU0lToQZuThQJ;5ii#<&bzT8xWw44AUw)a=5A2W!+YuJI?Ek|cqHyEnH>6I zN!$BJ)ly}T#dxDPgdR4#xkvuC>6e7|wz)T!Ci3s|kKVe@+`PHnLk?Z z*mXx%t!0^Y%zDYuNlnF4&kEuWbMIL2V7gRYtGMZ&mg%N{r1oF@z*V>UVfm#)t9Q)4 z^TJr?@Z?udB-dXl^uKuF{YQ4z`YRu#{w;Y}`X};m{D*KZa|MN&mtTvl&1rvIA?x}( z&iKCLvyuuv>x;Sz_$2GA4sNW@_{v+k$o!)@Z~gRt`IF1HRISum`1aQX?lqA{&!&1z z(Pmuzz^Tuu{kixr+vd^(h1%+$|6ZB%W>$Bz@>HXB3#;qmICJtNc1TT|%^?f zlZ^K?@3QfB@N50-SbJ-QfA7ynTDiAkBVjw)kZa9v>4=|~r^jBDmP!7%F3i-x zEdGs13cs)hj-gi}`@7-@MZ|hW-YA*J9)#~_IWwUY4?^xCYXN4TDKV?w( zRXTmfeMh$|`?i_p|FQY66|v1jr#yyfT9ir?~2^nAv=cb7u=*-Os$X17|z7Z9By-mau>AozFABR`1(VcmDXb_dlgR>pOPr zx4q&0Hri6kU0CFsx!U#fPAd7cT!S}di!DsCvFR=_lAGzOBH4dVX_gK9Q%f(ih0}AV z{5rt)Wn=DhDcuBlJBA<1FFV)Is9Cwg-QG7}S?O=bcD;HB+c`Gf%Y>%II=uN{X~J&2 zwq@Ej?Hf}z{E@L=wL?lP@hH!=HTny4+1|zo6dB&wQN$NMm(%37T%(X(Z$XCm^M{se zWMXWaSE~Nq68`r~%j1Va>*OY1d;VeGri|!0OtGpl&I^UYSZA+Z`m^GP&9xQ*e)enY zWLF=Ub-2{_pWgiU^Xffpisasl&N!%NSvCK_>454*rGD#{Pp+7f&Us;q?9s)=5!PkD z?DePWx_j+dc;v?g`T9FC;rBAQ?x^`ao;S~9?n@P4Hjbqqw|zZm5;E`JmIH~sQPW*q z+V6%oRxD{!K5|yN@^$0-iWEN0S$7S@`sXwX>`n6M`S3pSMtXa1=)d{r>scaq&DHUp zJlp-mX&p;T&oDa=KRcJOd8)y2s^Rw(-2XYAEx(|CEn$8{`(LHb+b;Tf;?5Qxr!x)P z7(X(w9o=l9Fz@(;3f9AqN@axdldhyc6x3OKH~NEPn&XUV*B+PkExNM1`ycxW`%UZ5 zTx_XeYrZ3Dq2%|7fp5~%$ce{gU8L)kCebsHZJH8+$O?%e^f3y-G z&up8yl$9y_0I_>KRdoqIpAB=+x_qFff#8 zGcYJXYi3^XkaWn^tM=-f_niE2gGrI+bqC9)c3IAj78MT@PLGHlk%y_zR3&Gsp4+3y zxiw2SEPLzPXx*smt1^~`1_&v1WnYcDvuf=v-__f$t(w2>uh`$NW&c0lJCibrhv}2@ z_r2xQi_d?uKfU+!9dUMk!HY8gPWaxg++m`;L{jstMy6YO{o<1o(|T(9N`n=jYuTK0 z`|~O}uc&xlPw(_&kDqbc1kUozn|CJoP6@OB)MKkZc;-o+zMS&!B$t1A;l9~&4&hOlb$ck97uB)Xplp|k z_R^K2Tz7dtA!3KD?rN&%C$GqVkF^ zd)c`^?9E#x{!062w%$Dz`R887?hnuAWj)d5%FfG6n{QHQzIL+QU0>fhuj?O)Rc`Y# zK7KY=rr=|x-aV}x_RW?@5(V`hJu0i5r*Gpb+P8CMsK~8T#|(bWczh`*c*kL1$8}Se z1*?^5?umW4e)r3onYYi0pJ>YO*dxB{rSLuvJN-%9yN{ZPYyR<7+iE6rZE>ihuGr;d zpLwrliB5g}>RR5qb-6LSmzDk8wRP)isd}^Z>tc3K(p>(|CUxfOL!>gpfIy?c~bZQcI*;wP(O0qxj- z9_|(r7ytMK8~LtT>(_Hy@9nIMVVq*lXB`*X=w5ER`m%UKM$^5Q+{cm|bANR?1g!t^ z^Gn2<`Z(@vwfv_uHLl2%GM=!U&T@z`S@ZHv)_A4s)4hvwwsBuKzPVbdZf<5util@e zBhF{5O4hbHZge=Zob`J4#fBPntG8~^4AW*$DNNt!YrygD?!Fc4B&$jl(hPJ@X&hvG z&Dp$-CF*hDSq_&&-Q2p1*_ECy5;knrubs2|AM^b@*)|b4jUgOJJMSoU$iO8Xx6MebU*Bcox<8s zbFIVwzE+uBxHNU$5z~nr2TZdkJaB$0*R*m^$>Q+WhVdpB@@`&w$M2$8|6C)R^;q-M zQpRA$$85ix!mBUI?`eLfC%NPHrK4Q&ZBK9Od=s7*d3D+EZO4w}edca6s_|)ju*K`d zCV?-jfA;JUGYOm^+kIrQ-Q6R<4EAo0{VuudzDyyj?hZ$*{InHcyjOpCs&G{zgE!mF zW)=U{j}JthQ`(j$?+U!kX(732+109g6OoRiEQbmf9lWC8H|;=n&8quOt?%L&XV+;< z9pkB2$y=h3k+)Y#h&Qt>(QgC0;9iI2dnG4Y_@=I2EZDjF^y9__uAR4M9^;v-p!|!W zWxdzVyN{+!JuA93F-Nj@yYtqU!FR$qA|yE*&lS90tR=*infPORm*~WdL#svp@qLl* z$gSsSnK(sZ$JzxSWKKwQnr3XWxV@gelylxio>PZhRK?6Evql`7e)>Aw%|%uZtkaU+ z*0Zk=t?E80$e+*e@MooDtlC`}KHD6Z-9ci8TYHy2?eH`;QgY;a=5dtaW53G8(9FL= z&s#zqCe_ACZJbqLvt&8b*0U+6-(6RY*0?>nQ9u7h{X4aGuK0x?%0>4HDc%#$eDB5W z=99`Q*&LGgP3MJUv6*npwgnj%*Ur2(*Dm{-&az!SJGE!N@U!@mQhIJu+BTEoU)yKt zMyL8sKDpLNZC^;~WEB&44qeMarb58VXw?L{pqEAaxTNO?tkmq@xBSxfmqt^|1U9|<9{P_l ze(fjInze_npFI9m>;HuOfS>L)%$Gi1Y@KBn-SIZ$r`tYGr6t}R+w;AFrt83W*vs_dyzPaGTT&?>@%UAE|ejoTV?%zt2?<@Dr zULX21{R>->5uwh!jcl%M_btNWK3<}!wRH0*hG1-@lH z)br_9TIi-SYieb-(9NsaE_-x2p2XGf74EdS@pSIoS=U3`f)>^P4?X*QVf54apZ_je z&K`2_@OOh;D=p#9y~#I}9`V+i@`c3TQh;o1JD?UOHF&<>r?6M0v& z_qWj3=+;b)2_M5|x!#z-IJNpn@3+-84g6YnR)0F2^rPPWhrp)N`YmgE+_vg*&eXE^ z%3twE!hYQ+;ZNUGa@^K)Pr7@yvEa~07CV1MYx%WjBpG(6ynXv&YparmYYzAG^Wi_m zKL`X=MmrPs$A5SHI^{(2vxq^=H?w__K;-_nw6l6&E%wTIFH$!hEj8R*gBzkv&zn zf3FVA_g0B|ICaHG>DKzypR)fj2z`9DVBJv`zc|Y`U9S&rD_G;u&AF9NH>czBQA78H zX$3u{TR)Vm3TbmM?h5`{TIc-m{>neq|C&$LKe10-b6D#~NZsW7K|jy`sW;;~*Q46! z_5QQ9)_!e{AKd>yk096u%OqUf5%Jbq#fUn_SJ{Koc~3C zs{Mo2A^#@iyMM5$TI1e1`;Fjyw@UNpNBR$X%FKA?-F;ek{}Y2*eRIF;%0F`87W2}F z#||F7{zCDek;DH?Q_agae7-(nsJp(+wO(2Fnxw$j-6CgMw{HD3r*e+DNP?jI?Z#gc zp#c^@x|04Z@XT!gw~O zpDpX{j@HvL;#OOa{9I-9*z=?d_ax&7oypS!<5-`ua4_q|uF2tNYvbnaZi zJ$;+{V^6zfZ+zz7XQrpWhPC`-+5R*S&sIL}BER}W=5JVAi~br_CGeQ8S7?`IJR)s*%NhnYHm;ZjKyx~^>Ib>OtekaTwY&i_oyaEVCs{yBB$+q&!#;N zGdr$yaL2-KZ62Q;u`7%o%r$$m?u&Hm)d$P|$JnSjn_s!87w@>U>ykC|GDltJ$ESNX z-7M-?jxf;=;%Yy#Be5}}bkh%J?pgBNtbg7JPq~pKlCtX3p@{~k4lPiv5O7=eF4EL|&=h+kXK56G=PcfZmAK&kYQL5B`YWeD8 z+&fjJwP6a8b2X;SOp_7+d(^XV%@K{lsJxTcOqbQgdrC*-uyyY8U|&?P@@oD++e^<= z?l?OpE-qh}W!c4iZPxc4QdlLUdUUDnl-s_K&o}$ng-7jP`Xk0G{IcnT6OP?4qIU6x+%f52*It(!5$$5XWbT9vi7u)m7!%b;X_h?p^(!=V|V{vSCW_?5Y#d3vY<+ zD2kPPzR)`3TE?r-7R9l}`gi=*LsP0Z?arL_*G%eJpxfD3%O;ywh`gM&FR{J5{OjHa zfx9&0uOt~?-PBa?w)if~w)0CTZjrojgGo5cWa_L;wVw+#?B_bI4RCMpTmCtNH}`0d z!ak=GJJ%K5wc>$SLK3-Ird-|b?0K_v7wS)h76xbSo${__(gUf8Qt`XIPkWZ+ zZs~rK$FT`{T1C#hQP6>iCTB@>?x^@}mB*$#SRLqNjpi zFt&c%;8fkYtj2Ni$3+)H?3|26R{iN|%_7($|kW3n}gXp zZg}&nyVP)6iKu0H&0n@^(Ih#o^&6&l-9NKy;xne8&E`+e1p0V(NzZ=sV#e(oPc(9K zimKiyMYbmEpA~jFxBdNc*6N@QnnoLIIL+=j9!|Kju|q@d$P~#B_jgvzW4a&7wtr=P z+x(c!s>#B&TDD9pWg<3q@ICZhvfk4(-noC)Meln@CT}{k{kTv6?)yFYfAR%BNmNe7^EL4~Dn(;@IrS23@{Qd*?FMsI~UADO` zd2!AcdA2uxt~|Fcdsq4%we+rjv85{S#nM#YbM7lPot(B=hVAUiCd%llVv zoPF+ALxoCXitk~)St%1^yTe_c{oS%}wwcHAo4gG%ib!X83 zE-kzPPsDCDpV%TE_*8Mtd)B3S8LQa~-mq@{%W;Q2p|9EC_TdHJI0}k6-u<7Ed8CY? zh*{=ypvfT7JhwjikfnJ2pFd`-&!viX{@So!JG1i7`jCv7PU|(d1TCyuq-?@k zTRUm`WpzQ_@D(37}Guu@>{nM&$UplFJ!dG2%<_n#fHtZkXDDHl;Rr+M&?Y)Q9?zOGl{5x`1+B2?; ze-d;4*fgEu-f*Bf2&to-sS|^32O@GrL;1{ zZ8K63-Xf#1W%4JN9YQ}jocH8)9ng<^xwOpU>Q7(hV^tcroDHXF$?YzYluPG7di3D7 zw~HQ5Tb=t^qyOEj-F{|oC-_bO`K-`(7rRrQ)2!a6-5Qe5F7qz%W-XUowf%GuR}RAs zj%kI?ri&MF)$>m=oO`eB)4hekiZ6|-_@~@sU&}vXmp#i;{s~jsO0{iujH7mj@$+wU-_Jh$=hxrI>J7CyXBKyet5!r9-}6q6`&sdL zvD1g!Srh8RYY#asRzK&uX44N3)lYwyl&mm0czSo%hM&{wH{3f>qW&)9qF+kQLf8HJ zrGH$X-2IiHaDG~H9>}HSdPd}|2$ADIKP#wSm`A0h zca7>K;e}H>)jh9ssOsFjrFi=KD$6sW(}bG*Gqt`tD$SS`eedj)Z9mTo)J5Nz`19_R zSpS{dO6$v2-#uPCtE0Jo{mp>wPb@f=dwk>3bKvY}Vp+j9<9G~%e6ig%&fovnPrMqT z+38{Z@p+p6wj!s6Xg-Saqk5VrceuJHOyo7q>&N(}O5^r+d?3cR_;9&g7`_TkK}=WC?bOxW>h)_oWB z1&g@e>|y>v|qyBY#X>x#OXCVol_f{Yr7YQYk%f0emS$7YtiNFUuRcot&iS$#fCRxXCP~?Fzf0kFQ#o?^89pL zlk)WEY4S5?MXZ=>HEHwLoO=;ElHZmdYRjldJLB{!(K!Et%L~WLMsvBjW<759=3)|V z)wz0Wx$o&2^_ux>q`o!nn`O=te?tG|HqGpM;|FVIr`)xV-B7H_uT^^bTDR+Azu0SY zzZzC;b@ZL>;QsjcLe{mm=@!2qZxqT;d2N`#Z2R>yF*mQdmY00U4P?J3RM2_zR-87M z)T~U76$*P+P4AJ6Ws*F1X^r}}TdhoYH|(9NRbTMbJN(R|rkg+Nqc?xo`;#-Fa%;|W z{g+Eiy?Pd^-@VST^x?y8yo*CF6(3tN)7Y!8$_QK5t!g@9MITN~ax;@{71+l+W=j7QR$p(eO%K zNx|~j!JkeyTSG``uOFtiEpP zqw7*>2B*8{&8%@ax>~BP`F_?9*}C-)`F|{K@|%8@EqCd$voW`ddgcWDnyk^26#Zh) zvIh~(XS83ee1C4L?(sVY-~QaR4%B$Q*>LrPBiABV7+%(zHg`t2mU7bX^Ci;{#edk< zX1yX~Mc3|f7QJs}@3dZ6+%Pu1b2L6uzRvhbY`yO0|Gg=`(MP4F%2XT||ByZ%s`a?0 z=c>4|_r^`7hqdk~-S69Fym|HYUeomZ*Y?Ce`o910@6(4r9&BcAf+*KWHxb{8f~OGJHoCvbbl@r&^lGRLIKUjLoDU+~a9 zbBEi~QmpF#>;1Jq-Ez5A`{~+=r)M6{lfQNP&?SLAWnvxtUe4T8yCd%|+?nv_)eZx$ z)Y>fpHgDgS9KFnIJUQda_1D(iuge}zGjX_nG0g6h%6wC^^!1%5+3vio_g=YY*KODS z zk-S^M@O;68<`~n&39tFzMymfz7G5IrOs-n#c>9hj`}EdggTU5LvsPC%Cbt-0XlHnL z)LkQUo{(La;kl%QJLVq@OkK^D*o016XRM00bc%XV9@=0Mec^qS)w|5!(_Dn2oRXL( z?>qZn$n$B9^~5y`c6K?a8HUum7N{A{S)){9w}H7d@*h|D#ZAp8ibU7OWQuNa?Js!2 zSFmEi-mbpS2V?Ip{#~;8cS&sKiaL!g&B>=b-zAi<=sNdymbEQMVbA5Mj$4!)g?nDH zv~B22yuQ_2?&YlP?S@A`YzX_nqh}=UYg0No>bb-;;SE22%}LHslQ`ur(WLNpOZ~$@ zFU71+sh^qypJ*MZRB&uND_Rm-ShMV1r+eKE<^8n^jp;LXY}VV}lD_y@?t!NZcU+n> z+lBYL!sDXsN$e-w>!&_{^2FoIk=Q$v6%)Rn5x7`YR#0T=;I=pPODRuC!TYi__Ki

X&!w{;_lT@BHFuYE93NwLRx$o>hJ` zdCID@>t4^58~q6rF5ReVS5sqqRlJ+Q&bc}7);`#K z`(3V}U*Pr4?lZS$E=rO38#&$kjCHj0>m!@GmjylMS|@b!_+Rl`Kenpg7q)x1*+$c> zT4MQcBj-u8>KnOhS>$iYz2deBJ@~iu%i}K+Ukp9|n^fI!oWJPH!g*`wNj1yabc!ai zTx?x_$LmtX&KB>@r5B_@ORP&uiQe>ldZ@|KqN42AwY#T3Iy0NS!`|NRkRod5d{vmh5B1cujf5smJYuJ+KY>r+K zk-)9^@w{bm+OwMCn=@~I{(Sy=KEtIM(=Rl*$m)7>_Ih}DD9SqMzbpJwct?B^Bd1KW z48KL2DvN=V<00j~<1&(MQLnd#^{CWK-rC$Y)BlNY<3(*|LTUD+No8}vE4lT43k|`GemlBp8cA7wMI{0yhHe$R98&I z6kp#t-ahjSraw%2Hg)N&$Fm~0h?!0Ip1^ZZGdBF}#-_>OUHH zW{GI-9p*D!G57PTqZb1042w>$UX}Fru5NnanTvOY~3^haXt(Jmepw-+SQy)LlO^11`Gl|KnCAvmwBP$7Io-4;??*e&t@u zoOCYkR`bOh>J^JN{@~jq|Kg3K@mgM|V`>41)dUlQGZf>vPkP8tFJP_TpgGIuNb(N9 zYcf~9e>m)3t@cZB-uVwl_b)is{C>sUxBnVH==})lQTeBF+wtxSW zi;j(Ix7|ekT@zcQ+F6y(gUtMRP2bPy5C#?7y(xBmI`5=H(^-tuAkWaetq)wXL>g zLQ=Djn(^PocWr;aoRe=q*Vd~3-|yGl48;`+$sFD4FD6bDJgDUE*Vdvc85zU(h-+O@ zjf&W58EvL-^&5F4uUo8RFKB+etS9=1%Q1#)7N3j`MLgFixRdx|`+j4ojgoB}YwoUE zqCIU_=+(u9UPnu!tl*G}y!4c84nDRl0->DFBfquL_2_e@%FS|IYG{1x55^}7;H-z06m^XcS* zJ4U{Dqt>qKZS&jU>OX1Yy1o}n9CPJwxz0Ja*?{ND*+pxk${tS4z2e(l~d+H%D_ z8{_UJPw4)-Y-!-Rjux4B2Yk5Siq1LM(Udsn*^bi_tfnn{^t77G?1SZTaW1bLDIHZW zS3a=YmvW-QZC85U?61eurk}AXzA>$-SVDNszC;fhxrCdmOtN=n##b+Txz@(wdXZ#( z?o*FdUOQIIZn)U_@z@a)=M4Ku?x*d$(u!+VJGe%=T#?YLl*@cOftk1bzChi|h?ttq zk1lX4nm_rJeDxB)kX26dyC2)<>dh?QB{$PTuOo5o@~$hdmre@xy)4~(;}K8nx}S3I zK2MQeohg0QM3gyDf=^<_s?d_z4{NM_&4c6i-mcHPl|Dg`=U8>(hLes}Z2T*JJDZ2z zb9$Mne`9Z!RMlM0sl{GrXL)T(+4W&h{g$BWrPi08#tOcFZ?17z?my>y`9uFz^FCR` z2`+u7<>V{L-Re@ge5Slz;M;>A^w#EGy5+xE$o~&hyv@WrjsMl7et(d&_3yGZ>$lt1 zps>5)`$;pO`s$YB8b8~N7iW2!wec73d-_$M<%0X-ecUUjcx;mWvi5j=+k44hlg}Tl z{UO`9#zg6FW90RkNA4}t$$1oMrdzmhKBbRz5i#&Sg@kd-6YcLDb|`52Pk+eSVE*H5f`~ObLU;hrwVrUebl9kDtEflmMw14Z`_WH%ozkKn3@o>fc_h;VZO^Us7 zME>v7bKmRUe=psCe)sRI*X#dEH~9IqUtrnVGwrWpi{NAdenp1*Uc>&6lOCjYh|itQ z>{B1$WYm$!>Bh1B5RcS|3G}t9)*XlcK=l6|F4qSf9$hRT++4as(X|khBDriDJ;4C zqFm>$heyR+1MBp}jN91~^|P){4#|z)%z8_C+0+dGh%B3xTaQnws_wV6StIqaBQIlj z$mwfqcHR6_&ON0{iY0F+-|FMeSDtRvG2-uDtz_3dF~Tdyz0`y=UtoK>lf5#_Ew0;E z-Sd29LnmwQOLcwHV6|%7av9s3au;*k&z<`9wPm4|W;e_Av)1?Cyq&yiV#fFS_jivz znxlAk-Rm9y&f0R%sM?(O!f*P4>AkHd#U)!0&C`GL;;7~3Ob3Mv$;VDcpPr#IOX}YG z$lX`}dL9aKJ2PXJOn~m(?{-E9?g_29mpCK2E&b}8j6AIzhq|y&xhG6^t#!$YFqUbo zmM%Vgb<2$q&Q+3?Q+GaMnI@3t%i0$|Jn#RkJ52SYG_L+3C=1p?i})Y&-CO zAAe-zjHo%ajYM@)RHb9dTOxkuj)xwog@>GU<4by06I^XpV88|jpsBeF)n1Vl6TZS#HE za??oe@*kcX59GJ2y^Q&2wdGPkzPUzW@Mh7&B_i&&D>PRvTq3-;_g0eG#qxLd3yz-H zbpMg8S-#UTK^f5-cXBmueds9GIJ~T9yxISGOWe-BPg>CvY@z$mR`UJh zo*w%LD|+}pEbOr_QrYz@$kTm!)tQcMQw`5v64Uvk^H1gR`I_JT1$lkf_a2&9I8XMU z;XkE^!i-A;Bu~ybGUb5m{f+hYTqSxN);%}SJ>Q%i8`3P05$RLPy(T&$dhxWmYd6KY zZw@)WCBsX6T~=e;q1+4a6|c<6)Lk0Ezxv8*^QSYds+B);cd-S|OAMNtpS1DAk~Eb$ zis9kl``4PYN3`z7q#e~+kzTZ;im%veyJv&Rl3RbiDNJqq4N@{& z?9G=7o8Jc}c)qQjHdE^6;^JAl^Og6;C%4tB77H9n$~^omW7(xw>&3Ti+0VA%!uq)e ze`jgAs`gtnX;q%u8821xZhG3>-%Bky8h3N(9l9$jYGV_7PHEoKl26XJWZeuC8>SU} zR_QvFBz5#*HwTa3;uN8!52ty0JiO+~a@e%db4qJAhqTpuuQ$s|c~u-_96k0lYZZ!Y zeI#+MtG+x?zi)BmoCAAZHVdli$lKmv+97Z|_K8zY{Aijy?sS0e@F0yBbl52)vggvzo2U8u>Qw|y^dR#+ZH$1YiwIMJ?FMx0fTGyb%8z1 zg7WEF7Ayu)h8e?c-2zlQF8dkH=LhD z^UE_^ojj^e{J3TH^0bR%{Oy}QIbM?fU7MPk_9+}Z&(6&+0~9rw@~}n>iy{c52u>e`Y!Et`wu;tyj_#KJaA5TVST4f`TqGU z!)xTr9)|vr_**BoX4#otU9v)D@vbvl*#Gt4T0J55!7?tjdym^sFWTTCGohf^JKJ}` zvJ|ODfA&n+`*hZZvx`rw%I=8WvF3e|M&Ew1sytTQ-XKvW(ZA#AzZI(! z zO$_hk7q>KIP)6BN6pHvm6$($5cqlMA<+c=4UKm(td$KH8Xi0_u4@}FF#=2;*q~9I( z$>%bJC-dIXVycXT3fVJVNuS(*$Dhe0WAcMLp-iA5M{(9C6Q)sjd*rJXgmLR(S266w|#Tun^yUGbWYF$q%O} zPtLqAE(0I(;ACL1hPjJ@fniA_e-&8K{`)RW+iIaq*2()|z+8vrY?Dpqi-A>TJd$FPm!ydNuJ5~A6qdAEC6%uo>()bECMs@*UN!S0%xts7oLbQ&09M8;S{CGTu%*{er%uo z;fTiMh(`jGOP)$Gu^yN_;b{bu=HbbT7i_>G|NJ7dU4M^E{(8|GEHU?)6w`%clXpJz eW>PvnS?Y@VWZmZ+e8vpM42K077}Ae}!Uh0s16mIN diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b343370e3..549d84424 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#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 -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d51..4f906e0c8 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f9553162f..107acd32c 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From a6c7236fa0c626abcb6e0c76fdc62bc6654e20b2 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 9 Jun 2021 07:42:18 +0100 Subject: [PATCH 2/8] ./gradlew licenseFormat --- src/main/java/dan200/computercraft/api/lua/ILuaObject.java | 3 +-- .../computercraft/api/peripheral/IPeripheralTile.java | 3 +-- .../java/dan200/computercraft/api/turtle/FakePlayer.java | 7 +++---- .../computercraft/client/render/ModelTransformer.java | 3 +-- .../fabric/events/ClientUnloadWorldEvent.java | 5 +++++ .../fabric/mixin/AffineTransformationAccess.java | 5 +++++ .../dan200/computercraft/fabric/mixin/BakedQuadAccess.java | 5 +++++ .../dan200/computercraft/fabric/mixin/ChatHudAccess.java | 5 +++++ .../computercraft/fabric/mixin/HeldItemRendererAccess.java | 5 +++++ .../computercraft/fabric/mixin/MinecraftServerAccess.java | 5 +++++ .../java/dan200/computercraft/fabric/mixin/MixinBlock.java | 3 +-- .../dan200/computercraft/fabric/mixin/MixinEntity.java | 3 +-- .../computercraft/fabric/mixin/MixinHeldItemRenderer.java | 3 +-- .../fabric/mixin/MixinItemFrameEntityRenderer.java | 3 +-- .../computercraft/fabric/mixin/MixinMinecraftClient.java | 3 +-- .../dan200/computercraft/fabric/mixin/MixinScreen.java | 3 +-- .../fabric/mixin/MixinServerPlayerInteractionManager.java | 5 +++++ .../computercraft/fabric/mixin/MixinServerWorld.java | 3 +-- .../java/dan200/computercraft/fabric/mixin/MixinWorld.java | 3 +-- .../computercraft/fabric/mixin/MixinWorldRenderer.java | 3 +-- .../computercraft/fabric/mixin/MusicDiscItemAccessor.java | 5 +++++ .../computercraft/fabric/mixin/SignBlockEntityAccess.java | 5 +++++ .../computercraft/fabric/mixin/SoundEventAccess.java | 5 +++++ .../computercraft/fabric/mixin/WorldSavePathAccess.java | 5 +++++ .../computercraft/shared/turtle/SignInspectHandler.java | 5 +++++ .../java/dan200/computercraft/shared/util/ItemStorage.java | 3 +-- 26 files changed, 76 insertions(+), 30 deletions(-) diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java index ff6d43d0a..8dfc72366 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java @@ -1,9 +1,8 @@ /* * 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; diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java index 01fd02cea..4b463dc1b 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java @@ -1,9 +1,8 @@ /* * 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 javax.annotation.Nonnull; diff --git a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java index 59cd782de..7c17ad6a2 100644 --- a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java +++ b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java @@ -1,9 +1,8 @@ /* - * 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 + * 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 java.util.Collection; diff --git a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java index f455fd883..4dbe7460c 100644 --- a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java +++ b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java @@ -1,9 +1,8 @@ /* * 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.render; import java.util.List; diff --git a/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java b/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java index bd2582dba..946c07f4d 100644 --- a/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java +++ b/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.events; import net.fabricmc.fabric.api.event.Event; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java index 11f98a308..c1cfb8d0a 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java index 67f8acbf9..9759c7016 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java index 08389f84b..b9c44bc9c 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java index c7cb0e3e3..f5224cecd 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java index a0c5436a1..022e55569 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java index c9eadae2c..c758b5935 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.shared.util.DropConsumer; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java index 5f57443e8..a9835de87 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.shared.util.DropConsumer; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java index bf0b86295..dfc91c6f5 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.client.render.ItemPocketRenderer; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java index 9480ee9e4..07bef1555 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.client.render.ItemPrintoutRenderer; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java index d734632a7..c99fbe55e 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.client.FrameInfo; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java index eda9d189a..7092a577f 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.shared.command.ClientCommands; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java index 0e8886ebb..c028dc960 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import dan200.computercraft.shared.ComputerCraftRegistry; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java index b59e42ffc..b392f0bff 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.shared.util.DropConsumer; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java index 80d1aec77..ef8d1745f 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import java.util.Collection; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java index 3f2180963..a65769185 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java @@ -1,9 +1,8 @@ /* * 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.fabric.mixin; import dan200.computercraft.client.render.CableHighlightRenderer; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java b/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java index 77757a1ce..dc41422ba 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import net.minecraft.item.MusicDiscItem; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java index a5b405f8a..153f22707 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java index 3fba7d8e2..fdaa67d05 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java index 06e8eb7a7..798606425 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java @@ -1,3 +1,8 @@ +/* + * 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.fabric.mixin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java b/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java index a885ced84..27bc2e98c 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java +++ b/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java @@ -1,3 +1,8 @@ +/* + * 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.shared.turtle; import java.util.HashMap; diff --git a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java index eb6f790f0..b5cbd096a 100644 --- a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java +++ b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java @@ -1,9 +1,8 @@ /* * 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.shared.util; import javax.annotation.Nonnull; From b429095f88c5c5324e8609c84c8e0e958fb1c8aa Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 9 Jun 2021 07:53:21 +0100 Subject: [PATCH 3/8] Reformat everything --- .../dan200/computercraft/ComputerCraft.java | 96 +- .../computercraft/ComputerCraftAPIImpl.java | 148 ++-- .../computercraft/api/ComputerCraftAPI.java | 151 ++-- .../api/client/TransformedModel.java | 75 +- .../api/filesystem/FileAttributes.java | 35 +- .../filesystem/FileOperationException.java | 21 +- .../api/filesystem/IFileSystem.java | 15 +- .../computercraft/api/filesystem/IMount.java | 39 +- .../api/filesystem/IWritableMount.java | 30 +- .../computercraft/api/lua/IArguments.java | 253 +++--- .../api/lua/IComputerSystem.java | 7 +- .../api/lua/IDynamicLuaObject.java | 13 +- .../dan200/computercraft/api/lua/ILuaAPI.java | 12 +- .../computercraft/api/lua/ILuaAPIFactory.java | 9 +- .../computercraft/api/lua/ILuaCallback.java | 5 +- .../computercraft/api/lua/ILuaContext.java | 5 +- .../computercraft/api/lua/ILuaFunction.java | 5 +- .../computercraft/api/lua/ILuaObject.java | 5 +- .../computercraft/api/lua/ILuaTask.java | 5 +- .../computercraft/api/lua/LuaException.java | 19 +- .../computercraft/api/lua/LuaFunction.java | 19 +- .../computercraft/api/lua/LuaValues.java | 99 ++- .../computercraft/api/lua/MethodResult.java | 91 +- .../api/lua/ObjectArguments.java | 48 +- .../computercraft/api/media/IMedia.java | 26 +- .../api/media/IMediaProvider.java | 9 +- .../api/network/IPacketNetwork.java | 13 +- .../api/network/IPacketReceiver.java | 17 +- .../api/network/IPacketSender.java | 7 +- .../computercraft/api/network/Packet.java | 54 +- .../api/network/wired/IWiredElement.java | 10 +- .../api/network/wired/IWiredNetwork.java | 24 +- .../network/wired/IWiredNetworkChange.java | 8 +- .../api/network/wired/IWiredNode.java | 30 +- .../api/network/wired/IWiredSender.java | 7 +- .../api/peripheral/IComputerAccess.java | 67 +- .../api/peripheral/IDynamicPeripheral.java | 24 +- .../api/peripheral/IPeripheral.java | 18 +- .../api/peripheral/IPeripheralProvider.java | 16 +- .../api/peripheral/IPeripheralTile.java | 11 +- .../api/peripheral/IWorkMonitor.java | 25 +- .../api/peripheral/NotAttachedException.java | 13 +- .../api/pocket/AbstractPocketUpgrade.java | 29 +- .../api/pocket/IPocketAccess.java | 21 +- .../api/pocket/IPocketUpgrade.java | 23 +- .../redstone/IBundledRedstoneProvider.java | 13 +- .../api/turtle/AbstractTurtleUpgrade.java | 37 +- .../computercraft/api/turtle/FakePlayer.java | 158 ++-- .../api/turtle/ITurtleAccess.java | 55 +- .../api/turtle/ITurtleCommand.java | 5 +- .../api/turtle/ITurtleUpgrade.java | 41 +- .../api/turtle/TurtleAnimation.java | 3 +- .../api/turtle/TurtleCommandResult.java | 41 +- .../computercraft/api/turtle/TurtleSide.java | 3 +- .../api/turtle/TurtleUpgradeType.java | 9 +- .../computercraft/api/turtle/TurtleVerb.java | 3 +- .../api/turtle/event/TurtleAction.java | 3 +- .../api/turtle/event/TurtleActionEvent.java | 36 +- .../api/turtle/event/TurtleAttackEvent.java | 33 +- .../api/turtle/event/TurtleBlockEvent.java | 103 ++- .../api/turtle/event/TurtleEvent.java | 23 +- .../turtle/event/TurtleInspectItemEvent.java | 43 +- .../turtle/event/TurtleInventoryEvent.java | 46 +- .../api/turtle/event/TurtlePlayerEvent.java | 20 +- .../api/turtle/event/TurtleRefuelEvent.java | 38 +- .../computercraft/client/ClientRegistry.java | 100 ++- .../client/ClientTableFormatter.java | 58 +- .../computercraft/client/FrameInfo.java | 28 +- .../client/gui/FixedWidthFontRenderer.java | 491 ++++++----- .../computercraft/client/gui/GuiComputer.java | 106 ++- .../client/gui/GuiDiskDrive.java | 33 +- .../computercraft/client/gui/GuiPrinter.java | 38 +- .../computercraft/client/gui/GuiPrintout.java | 106 ++- .../computercraft/client/gui/GuiTurtle.java | 93 +- .../client/gui/widgets/WidgetTerminal.java | 341 ++++--- .../client/gui/widgets/WidgetWrapper.java | 61 +- .../proxy/ComputerCraftProxyClient.java | 125 +-- .../client/render/CableHighlightRenderer.java | 52 +- .../client/render/ComputerBorderRenderer.java | 125 +-- .../client/render/ItemMapLikeRenderer.java | 135 +-- .../client/render/ItemPocketRenderer.java | 105 +-- .../client/render/ItemPrintoutRenderer.java | 78 +- .../client/render/ModelTransformer.java | 77 +- .../render/MonitorHighlightRenderer.java | 147 ++-- .../render/MonitorTextureBufferShader.java | 179 ++-- .../client/render/PrintoutRenderer.java | 240 ++--- .../render/TileEntityMonitorRenderer.java | 277 +++--- .../render/TileEntityTurtleRenderer.java | 220 ++--- .../client/render/TurtleModelLoader.java | 101 ++- .../client/render/TurtleMultiModel.java | 102 ++- .../client/render/TurtlePlayerRenderer.java | 27 +- .../client/render/TurtleSmartItemModel.java | 132 +-- .../computercraft/core/apis/ApiFactories.java | 26 +- .../core/apis/ComputerAccess.java | 138 +-- .../dan200/computercraft/core/apis/FSAPI.java | 358 +++++--- .../core/apis/FastLuaException.java | 20 +- .../computercraft/core/apis/HTTPAPI.java | 4 +- .../core/apis/IAPIEnvironment.java | 45 +- .../computercraft/core/apis/LuaDateTime.java | 409 +++++---- .../dan200/computercraft/core/apis/OSAPI.java | 329 ++++--- .../core/apis/PeripheralAPI.java | 329 ++++--- .../computercraft/core/apis/RedstoneAPI.java | 88 +- .../computercraft/core/apis/TableHelper.java | 209 +++-- .../computercraft/core/apis/TermAPI.java | 35 +- .../computercraft/core/apis/TermMethods.java | 210 +++-- .../core/apis/http/CheckUrl.java | 48 +- .../core/apis/http/HTTPRequestException.java | 11 +- .../core/apis/http/NetworkUtils.java | 134 +-- .../core/apis/http/Resource.java | 93 +- .../core/apis/http/ResourceGroup.java | 43 +- .../core/apis/http/ResourceQueue.java | 41 +- .../core/apis/http/options/Action.java | 8 +- .../core/apis/http/options/AddressRule.java | 64 +- .../apis/http/options/AddressRuleConfig.java | 189 ++-- .../core/apis/http/options/Options.java | 9 +- .../apis/http/options/PartialOptions.java | 45 +- .../core/apis/http/request/HttpRequest.java | 278 +++--- .../apis/http/request/HttpResponseHandle.java | 28 +- .../core/apis/http/websocket/Websocket.java | 217 +++-- .../apis/http/websocket/WebsocketHandle.java | 106 ++- .../apis/http/websocket/WebsocketHandler.java | 113 ++- .../core/asm/DeclaringClassLoader.java | 13 +- .../computercraft/core/asm/Generator.java | 415 +++++---- .../computercraft/core/asm/IntCache.java | 35 +- .../computercraft/core/asm/LuaMethod.java | 28 +- .../computercraft/core/asm/NamedMethod.java | 15 +- .../computercraft/core/asm/ObjectSource.java | 22 +- .../core/asm/PeripheralMethod.java | 36 +- .../computercraft/core/asm/Reflect.java | 104 ++- .../computercraft/core/asm/TaskCallback.java | 58 +- .../core/computer/ApiWrapper.java | 21 +- .../computercraft/core/computer/Computer.java | 128 ++- .../core/computer/ComputerExecutor.java | 460 ++++++---- .../core/computer/ComputerSide.java | 23 +- .../core/computer/ComputerSystem.java | 34 +- .../core/computer/ComputerThread.java | 357 +++++--- .../core/computer/Environment.java | 211 +++-- .../core/computer/IComputerEnvironment.java | 18 +- .../core/computer/MainThread.java | 107 ++- .../core/computer/MainThreadExecutor.java | 109 ++- .../core/computer/TimeoutState.java | 47 +- .../core/filesystem/ComboMount.java | 109 ++- .../core/filesystem/EmptyMount.java | 29 +- .../core/filesystem/FileMount.java | 392 +++++---- .../core/filesystem/FileSystemException.java | 8 +- .../filesystem/FileSystemWrapperMount.java | 192 ++-- .../core/filesystem/JarMount.java | 283 +++--- .../core/filesystem/MountWrapper.java | 366 +++++--- .../core/filesystem/ResourceMount.java | 276 +++--- .../core/filesystem/SubMount.java | 46 +- .../computercraft/core/lua/BasicFunction.java | 45 +- .../core/lua/CobaltLuaMachine.java | 689 ++++++++------- .../computercraft/core/lua/ILuaMachine.java | 18 +- .../computercraft/core/lua/MachineResult.java | 38 +- .../core/lua/ResultInterpreterFunction.java | 109 ++- .../core/lua/VarargArguments.java | 114 +-- .../computercraft/core/terminal/Terminal.java | 329 ++++--- .../core/tracking/ComputerTracker.java | 86 +- .../computercraft/core/tracking/Tracker.java | 20 +- .../computercraft/core/tracking/Tracking.java | 95 +- .../core/tracking/TrackingContext.java | 104 ++- .../core/tracking/TrackingField.java | 81 +- .../fabric/events/ClientUnloadWorldEvent.java | 5 +- .../mixin/AffineTransformationAccess.java | 22 +- .../fabric/mixin/BakedQuadAccess.java | 14 +- .../fabric/mixin/ChatHudAccess.java | 16 +- .../fabric/mixin/HeldItemRendererAccess.java | 22 +- .../fabric/mixin/MinecraftServerAccess.java | 14 +- .../fabric/mixin/MixinBlock.java | 26 +- .../fabric/mixin/MixinEntity.java | 26 +- .../fabric/mixin/MixinHeldItemRenderer.java | 59 +- .../mixin/MixinItemFrameEntityRenderer.java | 33 +- .../fabric/mixin/MixinMinecraftClient.java | 20 +- .../fabric/mixin/MixinScreen.java | 23 +- .../MixinServerPlayerInteractionManager.java | 24 +- .../fabric/mixin/MixinServerWorld.java | 20 +- .../fabric/mixin/MixinWorld.java | 51 +- .../fabric/mixin/MixinWorldRenderer.java | 59 +- .../fabric/mixin/MusicDiscItemAccessor.java | 5 +- .../fabric/mixin/SignBlockEntityAccess.java | 14 +- .../fabric/mixin/SoundEventAccess.java | 14 +- .../fabric/mixin/WorldSavePathAccess.java | 12 +- .../computercraft/shared/BundledRedstone.java | 55 +- .../shared/ComputerCraftRegistry.java | 380 ++++---- .../computercraft/shared/MediaProviders.java | 47 +- .../computercraft/shared/Peripherals.java | 52 +- .../computercraft/shared/PocketUpgrades.java | 4 +- .../shared/TurtlePermissions.java | 22 +- .../computercraft/shared/TurtleUpgrades.java | 10 +- .../shared/command/CommandComputerCraft.java | 1 - .../shared/command/CommandUtils.java | 69 +- .../shared/command/Exceptions.java | 35 +- .../arguments/ArgumentSerializers.java | 32 +- .../command/arguments/ChoiceArgumentType.java | 62 +- .../arguments/ComputerArgumentType.java | 74 +- .../arguments/ComputersArgumentType.java | 195 ++-- .../command/arguments/RepeatArgumentType.java | 125 +-- .../arguments/TrackingFieldArgumentType.java | 17 +- .../shared/command/builder/ArgCommand.java | 5 +- .../command/builder/CommandBuilder.java | 115 +-- .../command/builder/CommandNodeBuilder.java | 5 +- .../builder/HelpingArgumentBuilder.java | 205 +++-- .../shared/command/text/ChatHelpers.java | 2 +- .../command/text/ServerTableFormatter.java | 36 +- .../shared/command/text/TableBuilder.java | 103 ++- .../shared/command/text/TableFormatter.java | 116 +-- .../shared/common/BlockGeneric.java | 67 +- .../shared/common/ClientTerminal.java | 68 +- .../shared/common/ColourableRecipe.java | 57 +- .../shared/common/ContainerHeldItem.java | 60 +- .../DefaultBundledRedstoneProvider.java | 28 +- .../shared/common/IBundledRedstoneBlock.java | 7 +- .../shared/common/IColouredItem.java | 35 +- .../shared/common/ITerminal.java | 3 +- .../shared/common/ServerTerminal.java | 78 +- .../shared/common/TileGeneric.java | 68 +- .../shared/computer/apis/CommandAPI.java | 201 +++-- .../shared/computer/blocks/BlockComputer.java | 40 +- .../computer/blocks/BlockComputerBase.java | 153 ++-- .../computer/blocks/ComputerPeripheral.java | 39 +- .../shared/computer/blocks/ComputerProxy.java | 52 +- .../shared/computer/blocks/IComputerTile.java | 7 +- .../computer/blocks/TileCommandComputer.java | 110 ++- .../shared/computer/blocks/TileComputer.java | 76 +- .../computer/blocks/TileComputerBase.java | 348 +++++--- .../shared/computer/core/ClientComputer.java | 89 +- .../computer/core/ClientComputerRegistry.java | 8 +- .../shared/computer/core/ComputerFamily.java | 3 +- .../computer/core/ComputerRegistry.java | 51 +- .../shared/computer/core/ComputerState.java | 18 +- .../shared/computer/core/IComputer.java | 16 +- .../computer/core/IContainerComputer.java | 8 +- .../shared/computer/core/InputHandler.java | 83 +- .../shared/computer/core/InputState.java | 84 +- .../shared/computer/core/ServerComputer.java | 252 ++++-- .../computer/core/ServerComputerRegistry.java | 56 +- .../computer/inventory/ContainerComputer.java | 14 +- .../inventory/ContainerComputerBase.java | 79 +- .../inventory/ContainerViewComputer.java | 34 +- .../computer/items/ComputerItemFactory.java | 35 +- .../shared/computer/items/IComputerItem.java | 20 +- .../shared/computer/items/ItemComputer.java | 38 +- .../computer/items/ItemComputerBase.java | 64 +- .../recipe/ComputerConvertRecipe.java | 45 +- .../computer/recipe/ComputerFamilyRecipe.java | 72 +- .../recipe/ComputerUpgradeRecipe.java | 39 +- .../data/BlockNamedEntityLootCondition.java | 30 +- .../data/ConstantLootConditionSerializer.java | 22 +- .../data/HasComputerIdLootCondition.java | 31 +- .../data/PlayerCreativeLootCondition.java | 30 +- .../integration/ModMenuIntegration.java | 8 +- .../shared/media/items/ItemDisk.java | 102 ++- .../shared/media/items/ItemPrintout.java | 127 +-- .../shared/media/items/ItemTreasureDisk.java | 111 ++- .../shared/media/items/RecordMedia.java | 30 +- .../shared/media/recipes/DiskRecipe.java | 69 +- .../shared/media/recipes/PrintoutRecipe.java | 117 ++- .../shared/network/NetworkHandler.java | 145 +-- .../shared/network/NetworkMessage.java | 17 +- .../client/ChatTableClientMessage.java | 89 +- .../network/client/ComputerClientMessage.java | 35 +- .../client/ComputerDataClientMessage.java | 38 +- .../client/ComputerDeletedClientMessage.java | 17 +- .../client/ComputerTerminalClientMessage.java | 35 +- .../network/client/MonitorClientMessage.java | 37 +- .../client/PlayRecordClientMessage.java | 65 +- .../shared/network/client/TerminalState.java | 165 ++-- .../container/ComputerContainerData.java | 35 +- .../network/container/ContainerData.java | 36 +- .../container/HeldItemContainerData.java | 24 +- .../container/ViewComputerContainerData.java | 52 +- .../server/ComputerActionServerMessage.java | 57 +- .../network/server/ComputerServerMessage.java | 40 +- .../network/server/KeyEventServerMessage.java | 44 +- .../server/MouseEventServerMessage.java | 64 +- .../server/QueueEventServerMessage.java | 41 +- .../server/RequestComputerMessage.java | 33 +- .../commandblock/CommandBlockPeripheral.java | 49 +- .../peripheral/diskdrive/BlockDiskDrive.java | 74 +- .../diskdrive/ContainerDiskDrive.java | 75 +- .../diskdrive/DiskDrivePeripheral.java | 104 ++- .../peripheral/diskdrive/DiskDriveState.java | 15 +- .../peripheral/diskdrive/TileDiskDrive.java | 427 +++++---- .../peripheral/generic/GenericPeripheral.java | 12 +- .../peripheral/generic/data/BlockData.java | 9 +- .../peripheral/generic/data/DataHelpers.java | 9 +- .../peripheral/generic/data/ItemData.java | 14 +- .../generic/methods/InventoryMethods.java | 45 +- .../peripheral/modem/ModemPeripheral.java | 177 ++-- .../shared/peripheral/modem/ModemShapes.java | 22 +- .../shared/peripheral/modem/ModemState.java | 79 +- .../peripheral/modem/wired/BlockCable.java | 217 ++--- .../modem/wired/BlockWiredModemFull.java | 24 +- .../modem/wired/CableModemVariant.java | 77 +- .../peripheral/modem/wired/CableShapes.java | 181 ++-- .../modem/wired/ItemBlockCable.java | 140 +-- .../peripheral/modem/wired/TileCable.java | 320 ++++--- .../modem/wired/TileWiredModemFull.java | 324 ++++--- .../modem/wired/WiredModemElement.java | 53 +- .../wired/WiredModemLocalPeripheral.java | 104 ++- .../modem/wired/WiredModemPeripheral.java | 305 ++++--- .../modem/wireless/BlockWirelessModem.java | 76 +- .../modem/wireless/TileWirelessModem.java | 87 +- .../wireless/WirelessModemPeripheral.java | 34 +- .../modem/wireless/WirelessNetwork.java | 90 +- .../peripheral/monitor/BlockMonitor.java | 68 +- .../peripheral/monitor/ClientMonitor.java | 144 +-- .../peripheral/monitor/MonitorEdgeState.java | 60 +- .../peripheral/monitor/MonitorPeripheral.java | 67 +- .../peripheral/monitor/MonitorRenderer.java | 45 +- .../peripheral/monitor/ServerMonitor.java | 67 +- .../peripheral/monitor/TileMonitor.java | 598 ++++++++----- .../shared/peripheral/monitor/XYPair.java | 92 +- .../peripheral/printer/BlockPrinter.java | 76 +- .../peripheral/printer/ContainerPrinter.java | 104 ++- .../peripheral/printer/PrinterPeripheral.java | 71 +- .../peripheral/printer/TilePrinter.java | 398 +++++---- .../peripheral/speaker/BlockSpeaker.java | 31 +- .../peripheral/speaker/SpeakerPeripheral.java | 106 ++- .../peripheral/speaker/TileSpeaker.java | 40 +- .../shared/pocket/apis/PocketAPI.java | 92 +- .../pocket/core/PocketServerComputer.java | 141 +-- .../inventory/ContainerPocketComputer.java | 48 +- .../pocket/items/ItemPocketComputer.java | 358 +++++--- .../items/PocketComputerItemFactory.java | 26 +- .../pocket/peripherals/PocketModem.java | 38 +- .../peripherals/PocketModemPeripheral.java | 25 +- .../pocket/peripherals/PocketSpeaker.java | 31 +- .../peripherals/PocketSpeakerPeripheral.java | 16 +- .../recipes/PocketComputerUpgradeRecipe.java | 85 +- .../proxy/ComputerCraftProxyCommon.java | 95 +- .../shared/turtle/FurnaceRefuelHandler.java | 53 +- .../shared/turtle/SignInspectHandler.java | 28 +- .../shared/turtle/apis/TurtleAPI.java | 342 +++---- .../shared/turtle/blocks/BlockTurtle.java | 120 +-- .../shared/turtle/blocks/ITurtleTile.java | 12 +- .../shared/turtle/blocks/TileTurtle.java | 439 +++++---- .../shared/turtle/core/InteractDirection.java | 24 +- .../shared/turtle/core/MoveDirection.java | 30 +- .../shared/turtle/core/TurnDirection.java | 3 +- .../shared/turtle/core/TurtleBrain.java | 833 ++++++++++-------- .../turtle/core/TurtleCommandQueueEntry.java | 6 +- .../turtle/core/TurtleCompareCommand.java | 50 +- .../turtle/core/TurtleCompareToCommand.java | 25 +- .../turtle/core/TurtleCraftCommand.java | 41 +- .../turtle/core/TurtleDetectCommand.java | 20 +- .../shared/turtle/core/TurtleDropCommand.java | 74 +- .../turtle/core/TurtleEquipCommand.java | 75 +- .../turtle/core/TurtleInspectCommand.java | 56 +- .../shared/turtle/core/TurtleMoveCommand.java | 144 +-- .../turtle/core/TurtlePlaceCommand.java | 354 +++++--- .../shared/turtle/core/TurtlePlayer.java | 143 +-- .../turtle/core/TurtleRefuelCommand.java | 42 +- .../shared/turtle/core/TurtleSuckCommand.java | 136 +-- .../shared/turtle/core/TurtleToolCommand.java | 77 +- .../turtle/core/TurtleTransferToCommand.java | 39 +- .../shared/turtle/core/TurtleTurnCommand.java | 56 +- .../turtle/inventory/ContainerTurtle.java | 132 +-- .../shared/turtle/items/ITurtleItem.java | 18 +- .../shared/turtle/items/ItemTurtle.java | 142 +-- .../turtle/items/TurtleItemFactory.java | 47 +- .../shared/turtle/recipes/TurtleRecipe.java | 45 +- .../turtle/recipes/TurtleUpgradeRecipe.java | 144 +-- .../upgrades/CraftingTablePeripheral.java | 34 +- .../shared/turtle/upgrades/TurtleAxe.java | 21 +- .../turtle/upgrades/TurtleCraftingTable.java | 46 +- .../shared/turtle/upgrades/TurtleHoe.java | 42 +- .../upgrades/TurtleInventoryCrafting.java | 210 +++-- .../shared/turtle/upgrades/TurtleModem.java | 131 +-- .../shared/turtle/upgrades/TurtleShovel.java | 42 +- .../shared/turtle/upgrades/TurtleSpeaker.java | 71 +- .../shared/turtle/upgrades/TurtleSword.java | 28 +- .../shared/turtle/upgrades/TurtleTool.java | 222 ++--- .../computercraft/shared/util/Colour.java | 73 +- .../shared/util/ColourTracker.java | 18 +- .../shared/util/ColourUtils.java | 10 +- .../shared/util/CommentedConfigSpec.java | 42 +- .../computercraft/shared/util/Config.java | 421 ++++----- .../shared/util/DefaultInventory.java | 19 +- .../shared/util/DefaultSidedInventory.java | 17 +- .../shared/util/DirectionUtil.java | 43 +- .../shared/util/DropConsumer.java | 72 +- .../shared/util/FakeNetHandler.java | 224 +++-- .../shared/util/FixedPointTileEntityType.java | 40 +- .../computercraft/shared/util/Holiday.java | 3 +- .../shared/util/HolidayUtil.java | 27 +- .../computercraft/shared/util/IDAssigner.java | 95 +- .../shared/util/ImpostorRecipe.java | 71 +- .../shared/util/ImpostorShapelessRecipe.java | 92 +- .../shared/util/InventoryDelegate.java | 75 +- .../shared/util/InventoryUtil.java | 137 +-- .../computercraft/shared/util/IoUtil.java | 19 +- .../shared/util/ItemStorage.java | 237 +++-- .../computercraft/shared/util/NBTUtil.java | 290 +++--- .../computercraft/shared/util/Palette.java | 93 +- .../computercraft/shared/util/RecipeUtil.java | 104 ++- .../computercraft/shared/util/RecordUtil.java | 11 +- .../shared/util/RedstoneUtil.java | 14 +- .../shared/util/SingleIntArray.java | 12 +- .../computercraft/shared/util/StringUtil.java | 32 +- .../shared/util/ThreadUtils.java | 40 +- .../shared/util/TickScheduler.java | 44 +- .../shared/util/ValidatingSlot.java | 15 +- .../shared/util/WaterloggableHelpers.java | 28 +- .../computercraft/shared/util/WorldUtil.java | 196 +++-- .../shared/wired/InvariantChecker.java | 38 +- .../shared/wired/WiredNetwork.java | 503 ++++++----- .../shared/wired/WiredNetworkChange.java | 107 ++- .../computercraft/shared/wired/WiredNode.java | 134 +-- 409 files changed, 20797 insertions(+), 15102 deletions(-) diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java index 0e5ff357b..c77ba5d3c 100644 --- a/src/main/java/dan200/computercraft/ComputerCraft.java +++ b/src/main/java/dan200/computercraft/ComputerCraft.java @@ -6,15 +6,6 @@ package dan200.computercraft; -import static dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks; -import static dan200.computercraft.shared.ComputerCraftRegistry.init; - -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; -import java.util.concurrent.TimeUnit; - import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.core.apis.http.options.Action; import dan200.computercraft.core.apis.http.options.AddressRule; @@ -32,22 +23,31 @@ 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.*; -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 dan200.computercraft.shared.util.ImpostorRecipe; +import dan200.computercraft.shared.util.ImpostorShapelessRecipe; 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; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -public final class ComputerCraft implements ModInitializer { +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks; +import static dan200.computercraft.shared.ComputerCraftRegistry.init; + +public final class ComputerCraft implements ModInitializer +{ public static final String MOD_ID = "computercraft"; // Configuration fields @@ -61,16 +61,15 @@ public final class ComputerCraft implements ModInitializer { public static boolean commandRequireCreative = true; public static int computerThreads = 1; - public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(10); - public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(5); + public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( 10 ); + public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( 5 ); public static boolean httpEnabled = true; public static boolean httpWebsocketEnabled = true; public static List httpRules = Collections.unmodifiableList( Arrays.asList( - AddressRule.parse( "$private", null, Action.DENY.toPartial() ), - AddressRule.parse( "*", null, Action.ALLOW.toPartial() ) - )); - + AddressRule.parse( "$private", null, Action.DENY.toPartial() ), + AddressRule.parse( "*", null, Action.ALLOW.toPartial() ) + ) ); public static int httpMaxRequests = 16; public static int httpMaxWebsockets = 4; @@ -89,7 +88,7 @@ public final class ComputerCraft implements ModInitializer { public static int advancedTurtleFuelLimit = 100000; public static boolean turtlesObeyBlockProtection = true; public static boolean turtlesCanPush = true; - public static EnumSet turtleDisabledActions = EnumSet.noneOf(TurtleAction.class); + public static EnumSet turtleDisabledActions = EnumSet.noneOf( TurtleAction.class ); public static int computerTermWidth = 51; public static int computerTermHeight = 19; @@ -99,7 +98,6 @@ public final class ComputerCraft implements ModInitializer { public static int pocketTermWidth = 26; public static int pocketTermHeight = 20; - public static int monitorWidth = 8; public static int monitorHeight = 6; @@ -108,30 +106,32 @@ public final class ComputerCraft implements ModInitializer { public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry(); // Logging - public static final Logger log = LogManager.getLogger(MOD_ID); + 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 ItemGroup MAIN_GROUP = FabricItemGroupBuilder.build( new Identifier( MOD_ID, "main" ), () -> new ItemStack( ModBlocks.COMPUTER_NORMAL ) ); @Override - public void onInitialize() { + public void onInitialize() + { 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); + 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); - }); + 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 ); + } ); } -} \ No newline at end of file +} diff --git a/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java b/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java index 7176f3e61..f7e630d02 100644 --- a/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java +++ b/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java @@ -6,13 +6,6 @@ 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; @@ -31,18 +24,14 @@ 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.*; 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.fabricmc.loader.api.FabricLoader; import net.minecraft.block.entity.BlockEntity; import net.minecraft.resource.ReloadableResourceManager; import net.minecraft.server.MinecraftServer; @@ -52,24 +41,35 @@ import net.minecraft.util.math.Direction; import net.minecraft.world.BlockView; import net.minecraft.world.World; -import net.fabricmc.loader.api.FabricLoader; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; -public final class ComputerCraftAPIImpl implements IComputerCraftAPI { +public final class ComputerCraftAPIImpl implements IComputerCraftAPI +{ public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl(); private String version; - private ComputerCraftAPIImpl() { + private ComputerCraftAPIImpl() + { } - public static InputStream getResourceFile(String domain, String subPath) { + 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) { + if( server != null ) + { + ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).getServerResourceManager().getResourceManager(); + try + { + return manager.getResource( new Identifier( domain, subPath ) ) + .getInputStream(); + } + catch( IOException ignored ) + { return null; } } @@ -78,71 +78,86 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI { @Nonnull @Override - public String getInstalledVersion() { - if (this.version != null) { + 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"); + .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); + 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) { + 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) { + 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; + 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); + public void registerPeripheralProvider( @Nonnull IPeripheralProvider provider ) + { + Peripherals.register( provider ); } @Override - public void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade) { - TurtleUpgrades.register(upgrade); + public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade ) + { + TurtleUpgrades.register( upgrade ); } @Override - public void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider) { - BundledRedstone.register(provider); + 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); + 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); + public void registerMediaProvider( @Nonnull IMediaProvider provider ) + { + MediaProviders.register( provider ); } @Override - public void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade) { - PocketUpgrades.register(upgrade); + public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade ) + { + PocketUpgrades.register( upgrade ); } @Override @@ -153,28 +168,35 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI { @Nonnull @Override - public IPacketNetwork getWirelessNetwork() { + public IPacketNetwork getWirelessNetwork() + { return WirelessNetwork.getUniversal(); } @Override - public void registerAPIFactory(@Nonnull ILuaAPIFactory factory) { - ApiFactories.register(factory); + public void registerAPIFactory( @Nonnull ILuaAPIFactory factory ) + { + ApiFactories.register( factory ); } @Nonnull @Override - public IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element) { - return new WiredNode(element); + 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) { + 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; diff --git a/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java index 9699b6173..c1f8ed540 100644 --- a/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java +++ b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java @@ -6,9 +6,6 @@ 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; @@ -24,43 +21,53 @@ 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 net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockView; import net.minecraft.world.World; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * 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. */ -public final class ComputerCraftAPI { +public final class ComputerCraftAPI +{ private static IComputerCraftAPI instance; @Nonnull @Deprecated - public static String getAPIVersion() { + public static String getAPIVersion() + { return getInstalledVersion(); } @Nonnull - public static String getInstalledVersion() { + public static String getInstalledVersion() + { return getInstance().getInstalledVersion(); } @Nonnull - private static IComputerCraftAPI getInstance() { - if (instance != null) { + private static IComputerCraftAPI getInstance() + { + if( instance != null ) + { return instance; } - try { - return instance = (IComputerCraftAPI) Class.forName("dan200.computercraft.ComputerCraftAPIImpl") - .getField("INSTANCE") - .get(null); - } catch (ReflectiveOperationException e) { - throw new IllegalStateException("Cannot find ComputerCraft API", e); + try + { + return instance = (IComputerCraftAPI) Class.forName( "dan200.computercraft.ComputerCraftAPIImpl" ) + .getField( "INSTANCE" ) + .get( null ); + } + catch( ReflectiveOperationException e ) + { + throw new IllegalStateException( "Cannot find ComputerCraft API", e ); } } @@ -69,15 +76,16 @@ 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) { - return getInstance().createUniqueNumberedSaveDir(world, parentSubPath); + public static int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath ) + { + return getInstance().createUniqueNumberedSaveDir( world, parentSubPath ); } /** @@ -86,12 +94,12 @@ public final class ComputerCraftAPI { * 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. + * Computers' file system. * @see #createUniqueNumberedSaveDir(World, String) * @see IComputerAccess#mount(String, IMount) * @see IComputerAccess#mountWritable(String, IWritableMount) @@ -99,8 +107,9 @@ public final class ComputerCraftAPI { * @see IWritableMount */ @Nullable - public static IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity) { - return getInstance().createSaveDirMount(world, subPath, capacity); + public static IWritableMount createSaveDirMount( @Nonnull World world, @Nonnull String subPath, long capacity ) + { + return getInstance().createSaveDirMount( world, subPath, capacity ); } /** @@ -114,7 +123,7 @@ public final class ComputerCraftAPI { * "/data/computercraft/lua/rom". We construct a mount for that with * {@code createResourceMount("computercraft", "lua/rom")}. * - * @param domain The domain under which to look for resources. eg: "mymod". + * @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) @@ -122,8 +131,9 @@ public final class ComputerCraftAPI { * @see IMount */ @Nullable - public static IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath) { - return getInstance().createResourceMount(domain, subPath); + public static IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath ) + { + return getInstance().createResourceMount( domain, subPath ); } /** @@ -133,8 +143,9 @@ public final class ComputerCraftAPI { * @see IPeripheral * @see IPeripheralProvider */ - public static void registerPeripheralProvider(@Nonnull IPeripheralProvider provider) { - getInstance().registerPeripheralProvider(provider); + public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider ) + { + getInstance().registerPeripheralProvider( provider ); } /** @@ -155,8 +166,9 @@ public final class ComputerCraftAPI { * @param upgrade The turtle upgrade to register. * @see ITurtleUpgrade */ - public static void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade) { - getInstance().registerTurtleUpgrade(upgrade); + public static void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade ) + { + getInstance().registerTurtleUpgrade( upgrade ); } /** @@ -165,22 +177,24 @@ public final class ComputerCraftAPI { * @param provider The bundled redstone provider to register. * @see IBundledRedstoneProvider */ - public static void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider) { - getInstance().registerBundledRedstoneProvider(provider); + 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. + * @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. + * 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 Direction side) { - return getInstance().getBundledRedstoneOutput(world, pos, side); + public static int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) + { + return getInstance().getBundledRedstoneOutput( world, pos, side ); } /** @@ -189,12 +203,14 @@ public final class ComputerCraftAPI { * @param provider The media provider to register. * @see IMediaProvider */ - public static void registerMediaProvider(@Nonnull IMediaProvider provider) { - getInstance().registerMediaProvider(provider); + public static void registerMediaProvider( @Nonnull IMediaProvider provider ) + { + getInstance().registerMediaProvider( provider ); } - public static void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade) { - getInstance().registerPocketUpgrade(upgrade); + public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade ) + { + getInstance().registerPocketUpgrade( upgrade ); } /** @@ -202,12 +218,14 @@ public final class ComputerCraftAPI { * * @return The global wireless network, or {@code null} if it could not be fetched. */ - public static IPacketNetwork getWirelessNetwork() { + public static IPacketNetwork getWirelessNetwork() + { return getInstance().getWirelessNetwork(); } - public static void registerAPIFactory(@Nonnull ILuaAPIFactory factory) { - getInstance().registerAPIFactory(factory); + public static void registerAPIFactory( @Nonnull ILuaAPIFactory factory ) + { + getInstance().registerAPIFactory( factory ); } /** @@ -218,59 +236,62 @@ public final class ComputerCraftAPI { * @see IWiredElement#getNode() */ @Nonnull - public static IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element) { - return getInstance().createWiredNodeForElement(element); + public static IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element ) + { + return getInstance().createWiredNodeForElement( element ); } /** * 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 BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side) { - return getInstance().getWiredElementAt(world, pos, side); + public static IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ) + { + return getInstance().getWiredElementAt( world, pos, side ); } - public interface IComputerCraftAPI { + public interface IComputerCraftAPI + { @Nonnull String getInstalledVersion(); - int createUniqueNumberedSaveDir(@Nonnull World world, @Nonnull String parentSubPath); + int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath ); @Nullable - IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity); + IWritableMount createSaveDirMount( @Nonnull World world, @Nonnull String subPath, long capacity ); @Nullable - IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath); + IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath ); - void registerPeripheralProvider(@Nonnull IPeripheralProvider provider); + void registerPeripheralProvider( @Nonnull IPeripheralProvider provider ); void registerGenericSource( @Nonnull GenericSource source ); - void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade); + void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade ); - void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider); + void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider ); - int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side); + int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); - void registerMediaProvider(@Nonnull IMediaProvider provider); + void registerMediaProvider( @Nonnull IMediaProvider provider ); - void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade); + void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade ); @Nonnull IPacketNetwork getWirelessNetwork(); - void registerAPIFactory(@Nonnull ILuaAPIFactory factory); + void registerAPIFactory( @Nonnull ILuaAPIFactory factory ); @Nonnull - IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element); + IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element ); @Nullable - IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side); + IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ); } } diff --git a/src/main/java/dan200/computercraft/api/client/TransformedModel.java b/src/main/java/dan200/computercraft/api/client/TransformedModel.java index 911bfbb90..a62350b07 100644 --- a/src/main/java/dan200/computercraft/api/client/TransformedModel.java +++ b/src/main/java/dan200/computercraft/api/client/TransformedModel.java @@ -6,12 +6,9 @@ package dan200.computercraft.api.client; -import java.util.Objects; - -import javax.annotation.Nonnull; - import dan200.computercraft.fabric.mixin.AffineTransformationAccess; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModelManager; @@ -20,64 +17,78 @@ 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; +import javax.annotation.Nonnull; +import java.util.Objects; /** * A model to render, combined with a transformation matrix to apply. */ -@Environment (EnvType.CLIENT) -public final class TransformedModel { +@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, @Nonnull AffineTransformation matrix ) + { + this.model = Objects.requireNonNull( model ); + this.matrix = Objects.requireNonNull( matrix ); } - public TransformedModel(@Nonnull BakedModel model) { - this.model = Objects.requireNonNull(model); + public TransformedModel( @Nonnull BakedModel model ) + { + this.model = Objects.requireNonNull( model ); this.matrix = AffineTransformation.identity(); } - public static TransformedModel of(@Nonnull ModelIdentifier location) { + public static TransformedModel of( @Nonnull ModelIdentifier location ) + { BakedModelManager modelManager = MinecraftClient.getInstance() - .getBakedModelManager(); - return new TransformedModel(modelManager.getModel(location)); + .getBakedModelManager(); + return new TransformedModel( modelManager.getModel( location ) ); } - public static TransformedModel of(@Nonnull ItemStack item, @Nonnull AffineTransformation transform) { + public static TransformedModel of( @Nonnull ItemStack item, @Nonnull AffineTransformation transform ) + { BakedModel model = MinecraftClient.getInstance() - .getItemRenderer() - .getModels() - .getModel(item); - return new TransformedModel(model, transform); + .getItemRenderer() + .getModels() + .getModel( item ); + return new TransformedModel( model, transform ); } @Nonnull - public BakedModel getModel() { + public BakedModel getModel() + { return this.model; } @Nonnull - public AffineTransformation getMatrix() { + public AffineTransformation getMatrix() + { return this.matrix; } - public void push(MatrixStack matrixStack) { + 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()); + if( access.getTranslation() != null ) + { + matrixStack.translate( access.getTranslation().getX(), access.getTranslation().getY(), access.getTranslation().getZ() ); + } - matrixStack.multiply(this.matrix.getRotation2()); + matrixStack.multiply( this.matrix.getRotation2() ); - if (access.getScale() != null) - matrixStack.scale(access.getScale().getX(), access.getScale().getY(), access.getScale().getZ()); + if( access.getScale() != null ) + { + matrixStack.scale( access.getScale().getX(), access.getScale().getY(), access.getScale().getZ() ); + } - if (access.getRotation1() != null) - matrixStack.multiply(access.getRotation1()); + if( access.getRotation1() != null ) + { + matrixStack.multiply( access.getRotation1() ); + } } } diff --git a/src/main/java/dan200/computercraft/api/filesystem/FileAttributes.java b/src/main/java/dan200/computercraft/api/filesystem/FileAttributes.java index 2c79271a0..ce05e8181 100644 --- a/src/main/java/dan200/computercraft/api/filesystem/FileAttributes.java +++ b/src/main/java/dan200/computercraft/api/filesystem/FileAttributes.java @@ -13,59 +13,70 @@ 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); +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) { + FileAttributes( boolean isDirectory, long size ) + { this.isDirectory = isDirectory; this.size = size; } @Override - public FileTime lastModifiedTime() { + public FileTime lastModifiedTime() + { return EPOCH; } @Override - public FileTime lastAccessTime() { + public FileTime lastAccessTime() + { return EPOCH; } @Override - public FileTime creationTime() { + public FileTime creationTime() + { return EPOCH; } @Override - public boolean isRegularFile() { + public boolean isRegularFile() + { return !this.isDirectory; } @Override - public boolean isDirectory() { + public boolean isDirectory() + { return this.isDirectory; } @Override - public boolean isSymbolicLink() { + public boolean isSymbolicLink() + { return false; } @Override - public boolean isOther() { + public boolean isOther() + { return false; } @Override - public long size() { + public long size() + { return this.size; } @Override - public Object fileKey() { + public Object fileKey() + { return null; } } diff --git a/src/main/java/dan200/computercraft/api/filesystem/FileOperationException.java b/src/main/java/dan200/computercraft/api/filesystem/FileOperationException.java index a10ab5e43..a0d4de1aa 100644 --- a/src/main/java/dan200/computercraft/api/filesystem/FileOperationException.java +++ b/src/main/java/dan200/computercraft/api/filesystem/FileOperationException.java @@ -6,34 +6,37 @@ package dan200.computercraft.api.filesystem; -import java.io.IOException; -import java.util.Objects; - import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.IOException; +import java.util.Objects; /** * 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 { +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")); + 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")); + public FileOperationException( @Nonnull String message ) + { + super( Objects.requireNonNull( message, "message cannot be null" ) ); this.filename = null; } @Nullable - public String getFilename() { + public String getFilename() + { return this.filename; } } diff --git a/src/main/java/dan200/computercraft/api/filesystem/IFileSystem.java b/src/main/java/dan200/computercraft/api/filesystem/IFileSystem.java index 8736fd865..8c74731e3 100644 --- a/src/main/java/dan200/computercraft/api/filesystem/IFileSystem.java +++ b/src/main/java/dan200/computercraft/api/filesystem/IFileSystem.java @@ -13,31 +13,32 @@ 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; } diff --git a/src/main/java/dan200/computercraft/api/filesystem/IMount.java b/src/main/java/dan200/computercraft/api/filesystem/IMount.java index 055d0e464..f767bcd5a 100644 --- a/src/main/java/dan200/computercraft/api/filesystem/IMount.java +++ b/src/main/java/dan200/computercraft/api/filesystem/IMount.java @@ -6,18 +6,16 @@ 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.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)}. * @@ -29,26 +27,27 @@ import net.minecraft.world.World; * @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 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 contents) throws IOException; + void list( @Nonnull String path, @Nonnull List 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. + * 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; + ReadableByteChannel openForRead( @Nonnull String path ) throws IOException; /** * Get attributes about the given file. @@ -58,11 +57,13 @@ public interface IMount { * @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"); + 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)); + return new FileAttributes( this.isDirectory( path ), this.getSize( path ) ); } /** @@ -72,7 +73,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. @@ -81,7 +82,7 @@ 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 size of a file with a given path, in bytes. @@ -90,5 +91,5 @@ public interface IMount { * @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; + long getSize( @Nonnull String path ) throws IOException; } diff --git a/src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java b/src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java index 91ef9ae78..d39eec86c 100644 --- a/src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java +++ b/src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java @@ -6,18 +6,16 @@ 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.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. @@ -30,14 +28,15 @@ import net.minecraft.world.World; * @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. @@ -45,29 +44,29 @@ 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. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary - * positions when using binary mode. + * positions when using binary mode. * @throws IOException If the file could not be opened for writing. */ @Nonnull - WritableByteChannel openForWrite(@Nonnull String path) throws IOException; + 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. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary - * positions when using binary mode. + * positions when using binary mode. * @throws IOException If the file could not be opened for writing. */ @Nonnull - WritableByteChannel openForAppend(@Nonnull String path) throws IOException; + 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 @@ -84,7 +83,8 @@ public interface IWritableMount extends IMount { * @return The capacity of this mount, in bytes. */ @Nonnull - default OptionalLong getCapacity() { + default OptionalLong getCapacity() + { return OptionalLong.empty(); } } diff --git a/src/main/java/dan200/computercraft/api/lua/IArguments.java b/src/main/java/dan200/computercraft/api/lua/IArguments.java index 4d2e36e15..2d4d73983 100644 --- a/src/main/java/dan200/computercraft/api/lua/IArguments.java +++ b/src/main/java/dan200/computercraft/api/lua/IArguments.java @@ -6,19 +6,19 @@ package dan200.computercraft.api.lua; -import static dan200.computercraft.api.lua.LuaValues.checkFinite; - +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.nio.ByteBuffer; import java.util.Map; import java.util.Optional; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import static dan200.computercraft.api.lua.LuaValues.checkFinite; /** * The arguments passed to a function. */ -public interface IArguments { +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. @@ -26,12 +26,14 @@ public interface IArguments { * @param count The number of arguments to drop. * @return The new {@link IArguments} instance. */ - IArguments drop(int count); + IArguments drop( int count ); - default Object[] getAll() { + default Object[] getAll() + { Object[] result = new Object[this.count()]; - for (int i = 0; i < result.length; i++) { - result[i] = this.get(i); + for( int i = 0; i < result.length; i++ ) + { + result[i] = this.get( i ); } return result; } @@ -58,7 +60,7 @@ public interface IArguments { * @return The argument's value, or {@code null} if not present. */ @Nullable - Object get(int index); + Object get( int index ); /** * Get an argument as an integer. @@ -67,8 +69,9 @@ public interface IArguments { * @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); + default int getInt( int index ) throws LuaException + { + return (int) this.getLong( index ); } /** @@ -78,13 +81,15 @@ public interface IArguments { * @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); + 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(); + return LuaValues.checkFiniteNum( index, (Number) value ) + .longValue(); } /** @@ -94,8 +99,9 @@ public interface IArguments { * @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)); + default double getFiniteDouble( int index ) throws LuaException + { + return checkFinite( index, this.getDouble( index ) ); } /** @@ -106,10 +112,12 @@ public interface IArguments { * @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); + 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(); } @@ -121,10 +129,12 @@ public interface IArguments { * @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); + 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; } @@ -137,8 +147,9 @@ public interface IArguments { * @throws LuaException If the value is not a string. */ @Nonnull - default ByteBuffer getBytes(int index) throws LuaException { - return LuaValues.encode(this.getString(index)); + default ByteBuffer getBytes( int index ) throws LuaException + { + return LuaValues.encode( this.getString( index ) ); } /** @@ -149,10 +160,12 @@ public interface IArguments { * @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); + 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; } @@ -162,13 +175,14 @@ public interface IArguments { * * @param index The argument number. * @param klass The type of enum to parse. - * @param The type of enum to parse. + * @param 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 getEnum(int index, Class klass) throws LuaException { - return LuaValues.checkEnum(index, klass, this.getString(index)); + default > T getEnum( int index, Class klass ) throws LuaException + { + return LuaValues.checkEnum( index, klass, this.getString( index ) ); } /** @@ -179,10 +193,12 @@ public interface IArguments { * @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); + 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; } @@ -194,8 +210,9 @@ public interface IArguments { * @return The argument's value, or {@link Optional#empty()} if not present. This is a read only buffer. * @throws LuaException If the value is not a string. */ - default Optional optBytes(int index) throws LuaException { - return this.optString(index).map(LuaValues::encode); + default Optional optBytes( int index ) throws LuaException + { + return this.optString( index ).map( LuaValues::encode ); } /** @@ -205,15 +222,18 @@ public interface IArguments { * @return The argument's value, or {@link Optional#empty()} if not present. * @throws LuaException If the value is not a string. */ - default Optional optString(int index) throws LuaException { - Object value = this.get(index); - if (value == null) { + default Optional 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); + if( !(value instanceof String) ) + { + throw LuaValues.badArgumentOf( index, "string", value ); } - return Optional.of((String) value); + return Optional.of( (String) value ); } /** @@ -221,26 +241,28 @@ public interface IArguments { * * @param index The argument number. * @param klass The type of enum to parse. - * @param The type of enum to parse. + * @param 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 > Optional optEnum(int index, Class klass) throws LuaException { - Optional str = this.optString(index); - return str.isPresent() ? Optional.of(LuaValues.checkEnum(index, klass, str.get())) : Optional.empty(); + default > Optional optEnum( int index, Class klass ) throws LuaException + { + Optional 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. + * @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); + default double optDouble( int index, double def ) throws LuaException + { + return this.optDouble( index ).orElse( def ); } /** @@ -251,27 +273,31 @@ public interface IArguments { * @throws LuaException If the value is not a number. */ @Nonnull - default Optional optDouble(int index) throws LuaException { - Object value = this.get(index); - if (value == null) { + default Optional 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); + if( !(value instanceof Number) ) + { + throw LuaValues.badArgumentOf( index, "number", value ); } - return Optional.of(((Number) value).doubleValue()); + 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. + * @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); + default int optInt( int index, int def ) throws LuaException + { + return this.optInt( index ).orElse( def ); } /** @@ -282,8 +308,9 @@ public interface IArguments { * @throws LuaException If the value is not a number. */ @Nonnull - default Optional optInt(int index) throws LuaException { - return this.optLong(index).map(Long::intValue); + default Optional optInt( int index ) throws LuaException + { + return this.optLong( index ).map( Long::intValue ); } /** @@ -293,40 +320,45 @@ public interface IArguments { * @return The argument's value, or {@link Optional#empty()} if not present. * @throws LuaException If the value is not a number. */ - default Optional optLong(int index) throws LuaException { - Object value = this.get(index); - if (value == null) { + default Optional 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); + if( !(value instanceof Number) ) + { + throw LuaValues.badArgumentOf( index, "number", value ); } - return Optional.of(LuaValues.checkFiniteNum(index, (Number) value) - .longValue()); + 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. + * @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); + 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. + * @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); + default double optFiniteDouble( int index, double def ) throws LuaException + { + return this.optFiniteDouble( index ).orElse( def ); } /** @@ -336,10 +368,12 @@ public interface IArguments { * @return The argument's value, or {@link Optional#empty()} if not present. * @throws LuaException If the value is not finite. */ - default Optional optFiniteDouble(int index) throws LuaException { - Optional value = this.optDouble(index); - if (value.isPresent()) { - LuaValues.checkFiniteNum(index, value.get()); + default Optional optFiniteDouble( int index ) throws LuaException + { + Optional value = this.optDouble( index ); + if( value.isPresent() ) + { + LuaValues.checkFiniteNum( index, value.get() ); } return value; } @@ -348,12 +382,13 @@ public interface IArguments { * Get an argument as a boolean. * * @param index The argument number. - * @param def The default value, if this argument is not given. + * @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); + default boolean optBoolean( int index, boolean def ) throws LuaException + { + return this.optBoolean( index ).orElse( def ); } /** @@ -363,39 +398,44 @@ public interface IArguments { * @return The argument's value, or {@link Optional#empty()} if not present. * @throws LuaException If the value is not a boolean. */ - default Optional optBoolean(int index) throws LuaException { - Object value = this.get(index); - if (value == null) { + default Optional 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); + if( !(value instanceof Boolean) ) + { + throw LuaValues.badArgumentOf( index, "boolean", value ); } - return Optional.of((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. + * @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); + 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. + * @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 def) throws LuaException { - return this.optTable(index).orElse(def); + default Map optTable( int index, Map def ) throws LuaException + { + return this.optTable( index ).orElse( def ); } /** @@ -405,14 +445,17 @@ public interface IArguments { * @return The argument's value, or {@link Optional#empty()} if not present. * @throws LuaException If the value is not a table. */ - default Optional> optTable(int index) throws LuaException { - Object value = this.get(index); - if (value == null) { + default Optional> 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); + if( !(value instanceof Map) ) + { + throw LuaValues.badArgumentOf( index, "map", value ); } - return Optional.of((Map) value); + return Optional.of( (Map) value ); } } diff --git a/src/main/java/dan200/computercraft/api/lua/IComputerSystem.java b/src/main/java/dan200/computercraft/api/lua/IComputerSystem.java index 6495786ca..d9069b52a 100644 --- a/src/main/java/dan200/computercraft/api/lua/IComputerSystem.java +++ b/src/main/java/dan200/computercraft/api/lua/IComputerSystem.java @@ -6,15 +6,16 @@ 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. */ -public interface IComputerSystem extends IComputerAccess { +public interface IComputerSystem extends IComputerAccess +{ /** * Get the file system for this computer. * diff --git a/src/main/java/dan200/computercraft/api/lua/IDynamicLuaObject.java b/src/main/java/dan200/computercraft/api/lua/IDynamicLuaObject.java index 9365ee574..49c4d6a47 100644 --- a/src/main/java/dan200/computercraft/api/lua/IDynamicLuaObject.java +++ b/src/main/java/dan200/computercraft/api/lua/IDynamicLuaObject.java @@ -6,17 +6,18 @@ package dan200.computercraft.api.lua; -import javax.annotation.Nonnull; - import dan200.computercraft.api.peripheral.IDynamicPeripheral; +import javax.annotation.Nonnull; + /** * 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 { +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. * @@ -29,12 +30,12 @@ public interface IDynamicLuaObject { /** * 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 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; + MethodResult callMethod( @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments ) throws LuaException; } diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaAPI.java b/src/main/java/dan200/computercraft/api/lua/ILuaAPI.java index 4d6115f3b..ca33136dc 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaAPI.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaAPI.java @@ -18,7 +18,8 @@ import dan200.computercraft.api.ComputerCraftAPI; * @see ILuaAPIFactory * @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory) */ -public interface ILuaAPI { +public interface ILuaAPI +{ /** * Get the globals this API will be assigned to. This will override any other global, so you should * @@ -31,13 +32,15 @@ public interface ILuaAPI { * * 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() + { } /** @@ -45,6 +48,7 @@ public interface ILuaAPI { * * This should reset the state of the object, disposing any remaining file handles, or other resources. */ - default void shutdown() { + default void shutdown() + { } } diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaAPIFactory.java b/src/main/java/dan200/computercraft/api/lua/ILuaAPIFactory.java index 93567e1f7..9b4fbbc47 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaAPIFactory.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaAPIFactory.java @@ -6,11 +6,11 @@ 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. * @@ -18,7 +18,8 @@ import dan200.computercraft.api.ComputerCraftAPI; * @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory) */ @FunctionalInterface -public interface ILuaAPIFactory { +public interface ILuaAPIFactory +{ /** * Create a new API instance for a given computer. * @@ -26,5 +27,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 ); } diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaCallback.java b/src/main/java/dan200/computercraft/api/lua/ILuaCallback.java index ec7769afa..b24e4b25e 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaCallback.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaCallback.java @@ -13,7 +13,8 @@ import javax.annotation.Nonnull; * * @see MethodResult#yield(Object[], ILuaCallback) */ -public interface ILuaCallback { +public interface ILuaCallback +{ /** * Resume this coroutine. * @@ -22,5 +23,5 @@ public interface ILuaCallback { * @throws LuaException On an error. */ @Nonnull - MethodResult resume(Object[] args) throws LuaException; + MethodResult resume( Object[] args ) throws LuaException; } diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaContext.java b/src/main/java/dan200/computercraft/api/lua/ILuaContext.java index a26f84372..d871786e4 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaContext.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaContext.java @@ -12,7 +12,8 @@ import javax.annotation.Nonnull; * 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 +{ /** * 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. @@ -25,5 +26,5 @@ public interface ILuaContext { * @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; } diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaFunction.java b/src/main/java/dan200/computercraft/api/lua/ILuaFunction.java index 1218d7a4f..70d900c2c 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaFunction.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaFunction.java @@ -15,7 +15,8 @@ import javax.annotation.Nonnull; * @see MethodResult#of(Object) */ @FunctionalInterface -public interface ILuaFunction { +public interface ILuaFunction +{ /** * Call this function with a series of arguments. Note, this will always be called on the computer thread, and so its implementation must be * thread-safe. @@ -25,5 +26,5 @@ public interface ILuaFunction { * @throws LuaException Upon Lua errors. */ @Nonnull - MethodResult call(@Nonnull IArguments arguments) throws LuaException; + MethodResult call( @Nonnull IArguments arguments ) throws LuaException; } diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java index 8dfc72366..eba77bc19 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java @@ -8,10 +8,11 @@ package dan200.computercraft.api.lua; import javax.annotation.Nonnull; import javax.annotation.Nullable; -public interface ILuaObject { +public interface ILuaObject +{ @Nonnull String[] getMethodNames(); @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; } diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaTask.java b/src/main/java/dan200/computercraft/api/lua/ILuaTask.java index f80238d23..44a429ed4 100644 --- a/src/main/java/dan200/computercraft/api/lua/ILuaTask.java +++ b/src/main/java/dan200/computercraft/api/lua/ILuaTask.java @@ -15,13 +15,14 @@ import javax.annotation.Nullable; * @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. * @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. + * to throw appropriate errors if the wrong arguments are supplied to your method. */ @Nullable Object[] execute() throws LuaException; diff --git a/src/main/java/dan200/computercraft/api/lua/LuaException.java b/src/main/java/dan200/computercraft/api/lua/LuaException.java index 8f479b38b..21d799c4a 100644 --- a/src/main/java/dan200/computercraft/api/lua/LuaException.java +++ b/src/main/java/dan200/computercraft/api/lua/LuaException.java @@ -11,19 +11,22 @@ 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(@Nullable String message) { - super(message); + public LuaException( @Nullable String message ) + { + super( message ); this.hasLevel = false; this.level = 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; } @@ -33,7 +36,8 @@ public class LuaException extends Exception { * * @return Whether this has an explicit level. */ - public boolean hasLevel() { + public boolean hasLevel() + { return this.hasLevel; } @@ -42,7 +46,8 @@ public class LuaException extends Exception { * * @return The level to raise the error at. */ - public int getLevel() { + public int getLevel() + { return this.level; } } diff --git a/src/main/java/dan200/computercraft/api/lua/LuaFunction.java b/src/main/java/dan200/computercraft/api/lua/LuaFunction.java index 3e4421328..064149466 100644 --- a/src/main/java/dan200/computercraft/api/lua/LuaFunction.java +++ b/src/main/java/dan200/computercraft/api/lua/LuaFunction.java @@ -6,17 +6,13 @@ 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; +import java.lang.annotation.*; +import java.util.Map; +import java.util.Optional; + /** * Used to mark a Java function which is callable from Lua. * @@ -41,9 +37,10 @@ import dan200.computercraft.api.peripheral.IPeripheral; * {@link MethodResult#of(Object...)}. */ @Documented -@Retention (RetentionPolicy.RUNTIME) -@Target (ElementType.METHOD) -public @interface LuaFunction { +@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. * diff --git a/src/main/java/dan200/computercraft/api/lua/LuaValues.java b/src/main/java/dan200/computercraft/api/lua/LuaValues.java index b20fbbc3b..a78091060 100644 --- a/src/main/java/dan200/computercraft/api/lua/LuaValues.java +++ b/src/main/java/dan200/computercraft/api/lua/LuaValues.java @@ -6,19 +6,20 @@ package dan200.computercraft.api.lua; -import java.nio.ByteBuffer; -import java.util.Map; - import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.nio.ByteBuffer; +import java.util.Map; /** * Various utility functions for operating with Lua values. * * @see IArguments */ -public final class LuaValues { - private LuaValues() { +public final class LuaValues +{ + private LuaValues() + { } /** @@ -28,41 +29,45 @@ public final class LuaValues { * @return The encoded string. */ @Nonnull - public static ByteBuffer encode(@Nonnull String string) { + 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); + 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(); + 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 index The argument number, starting from 0. * @param expected The expected type for this argument. - * @param actual The actual value provided 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)); + 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 index The argument number, starting from 0. * @param expected The expected type for this argument. - * @param actual The provided 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 + ")"); + public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual ) + { + return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" ); } /** @@ -72,20 +77,26 @@ public final class LuaValues { * @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) { + public static String getType( @Nullable Object value ) + { + if( value == null ) + { return "nil"; } - if (value instanceof String) { + if( value instanceof String ) + { return "string"; } - if (value instanceof Boolean) { + if( value instanceof Boolean ) + { return "boolean"; } - if (value instanceof Number) { + if( value instanceof Number ) + { return "number"; } - if (value instanceof Map) { + if( value instanceof Map ) + { return "table"; } return "userdata"; @@ -99,8 +110,9 @@ public final class LuaValues { * @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()); + public static Number checkFiniteNum( int index, Number value ) throws LuaException + { + checkFinite( index, value.doubleValue() ); return value; } @@ -112,9 +124,11 @@ public final class LuaValues { * @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)); + public static double checkFinite( int index, double value ) throws LuaException + { + if( !Double.isFinite( value ) ) + { + throw badArgument( index, "number", getNumericType( value ) ); } return value; } @@ -127,14 +141,18 @@ public final class LuaValues { * @return This value's numeric type. */ @Nonnull - public static String getNumericType(double value) { - if (Double.isNaN(value)) { + public static String getNumericType( double value ) + { + if( Double.isNaN( value ) ) + { return "nan"; } - if (value == Double.POSITIVE_INFINITY) { + if( value == Double.POSITIVE_INFINITY ) + { return "inf"; } - if (value == Double.NEGATIVE_INFINITY) { + if( value == Double.NEGATIVE_INFINITY ) + { return "-inf"; } return "number"; @@ -146,18 +164,21 @@ public final class LuaValues { * @param index The argument index to check. * @param klass The class of the enum instance. * @param value The value to extract. - * @param The type of enum we are extracting. + * @param 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 checkEnum(int index, Class klass, String value) throws LuaException { - for (T possibility : klass.getEnumConstants()) { - if (possibility.name() - .equalsIgnoreCase(value)) { + public static > T checkEnum( int index, Class 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 + ")"); + throw new LuaException( "bad argument #" + (index + 1) + " (unknown option " + value + ")" ); } } diff --git a/src/main/java/dan200/computercraft/api/lua/MethodResult.java b/src/main/java/dan200/computercraft/api/lua/MethodResult.java index 33e2fc037..c7ee1d3ae 100644 --- a/src/main/java/dan200/computercraft/api/lua/MethodResult.java +++ b/src/main/java/dan200/computercraft/api/lua/MethodResult.java @@ -6,36 +6,38 @@ package dan200.computercraft.api.lua; +import dan200.computercraft.api.peripheral.IComputerAccess; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; 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); +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) { + private MethodResult( Object[] arguments, ILuaCallback callback ) + { this.result = arguments; this.callback = callback; this.adjust = 0; } - private MethodResult(Object[] arguments, ILuaCallback callback, int adjust) { + private MethodResult( Object[] arguments, ILuaCallback callback, int adjust ) + { this.result = arguments; this.callback = callback; this.adjust = adjust; @@ -47,7 +49,8 @@ public final class MethodResult { * @return A method result which returns immediately with no values. */ @Nonnull - public static MethodResult of() { + public static MethodResult of() + { return empty; } @@ -64,8 +67,9 @@ public final class MethodResult { * @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); + public static MethodResult of( @Nullable Object value ) + { + return new MethodResult( new Object[] { value }, null ); } /** @@ -75,43 +79,47 @@ public final class MethodResult { * @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); + 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 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); + 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); - }); + 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 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); + public static MethodResult pullEventRaw( @Nullable String filter, @Nonnull ILuaCallback callback ) + { + Objects.requireNonNull( callback, "callback cannot be null" ); + return new MethodResult( new Object[] { filter }, callback ); } /** @@ -119,27 +127,31 @@ public final class MethodResult { * {@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() + * @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); + 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() { + public Object[] getResult() + { return this.result; } @Nullable - public ILuaCallback getCallback() { + public ILuaCallback getCallback() + { return this.callback; } - public int getErrorAdjust() { + public int getErrorAdjust() + { return this.adjust; } @@ -150,13 +162,16 @@ public final class MethodResult { * @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"); + public MethodResult adjustError( int adjust ) + { + if( adjust < 0 ) + { + throw new IllegalArgumentException( "cannot adjust by a negative amount" ); } - if (adjust == 0 || this.callback == null) { + if( adjust == 0 || this.callback == null ) + { return this; } - return new MethodResult(this.result, this.callback, this.adjust + adjust); + return new MethodResult( this.result, this.callback, this.adjust + adjust ); } } diff --git a/src/main/java/dan200/computercraft/api/lua/ObjectArguments.java b/src/main/java/dan200/computercraft/api/lua/ObjectArguments.java index 0c47d52e8..d0c58833b 100644 --- a/src/main/java/dan200/computercraft/api/lua/ObjectArguments.java +++ b/src/main/java/dan200/computercraft/api/lua/ObjectArguments.java @@ -6,61 +6,71 @@ package dan200.computercraft.api.lua; +import javax.annotation.Nullable; 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 { +public final class ObjectArguments implements IArguments +{ private static final IArguments EMPTY = new ObjectArguments(); private final List args; @Deprecated - @SuppressWarnings ("unused") - public ObjectArguments(IArguments arguments) { + @SuppressWarnings( "unused" ) + public ObjectArguments( IArguments arguments ) + { throw new IllegalStateException(); } - public ObjectArguments(Object... args) { - this.args = Arrays.asList(args); + public ObjectArguments( Object... args ) + { + this.args = Arrays.asList( args ); } - public ObjectArguments(List args) { - this.args = Objects.requireNonNull(args); + public ObjectArguments( List args ) + { + this.args = Objects.requireNonNull( args ); } @Override - public IArguments drop(int count) { - if (count < 0) { - throw new IllegalStateException("count cannot be negative"); + public IArguments drop( int count ) + { + if( count < 0 ) + { + throw new IllegalStateException( "count cannot be negative" ); } - if (count == 0) { + if( count == 0 ) + { return this; } - if (count >= this.args.size()) { + if( count >= this.args.size() ) + { return EMPTY; } - return new ObjectArguments(this.args.subList(count, this.args.size())); + return new ObjectArguments( this.args.subList( count, this.args.size() ) ); } @Override - public Object[] getAll() { + public Object[] getAll() + { return this.args.toArray(); } @Override - public int count() { + public int count() + { return this.args.size(); } @Nullable @Override - public Object get(int index) { - return index >= this.args.size() ? null : this.args.get(index); + public Object get( int index ) + { + return index >= this.args.size() ? null : this.args.get( index ); } } diff --git a/src/main/java/dan200/computercraft/api/media/IMedia.java b/src/main/java/dan200/computercraft/api/media/IMedia.java index c002aab23..986da717e 100644 --- a/src/main/java/dan200/computercraft/api/media/IMedia.java +++ b/src/main/java/dan200/computercraft/api/media/IMedia.java @@ -6,22 +6,22 @@ package dan200.computercraft.api.media; -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; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Represents an item that can be placed in a disk drive and used by a Computer. * * 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. * @@ -29,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. @@ -38,7 +38,8 @@ 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; } @@ -49,7 +50,8 @@ public interface IMedia { * @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; } @@ -60,7 +62,8 @@ 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; } @@ -71,14 +74,15 @@ public interface IMedia { * @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() + * 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(String, String) */ @Nullable - default IMount createDataMount(@Nonnull ItemStack stack, @Nonnull World world) { + default IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) + { return null; } } diff --git a/src/main/java/dan200/computercraft/api/media/IMediaProvider.java b/src/main/java/dan200/computercraft/api/media/IMediaProvider.java index 28bf56bd7..7afa1e632 100644 --- a/src/main/java/dan200/computercraft/api/media/IMediaProvider.java +++ b/src/main/java/dan200/computercraft/api/media/IMediaProvider.java @@ -6,18 +6,19 @@ 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. * @@ -26,5 +27,5 @@ public interface IMediaProvider { * @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider) */ @Nullable - IMedia getMedia(@Nonnull ItemStack stack); + IMedia getMedia( @Nonnull ItemStack stack ); } diff --git a/src/main/java/dan200/computercraft/api/network/IPacketNetwork.java b/src/main/java/dan200/computercraft/api/network/IPacketNetwork.java index 324505ff6..b897717c6 100644 --- a/src/main/java/dan200/computercraft/api/network/IPacketNetwork.java +++ b/src/main/java/dan200/computercraft/api/network/IPacketNetwork.java @@ -14,20 +14,21 @@ 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. @@ -41,11 +42,11 @@ public interface IPacketNetwork { * 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 @@ -55,5 +56,5 @@ public interface IPacketNetwork { * @see #transmitSameDimension(Packet, double) * @see IPacketReceiver#receiveDifferentDimension(Packet) */ - void transmitInterdimensional(@Nonnull Packet packet); + void transmitInterdimensional( @Nonnull Packet packet ); } diff --git a/src/main/java/dan200/computercraft/api/network/IPacketReceiver.java b/src/main/java/dan200/computercraft/api/network/IPacketReceiver.java index 0b1c2c200..660344a2b 100644 --- a/src/main/java/dan200/computercraft/api/network/IPacketReceiver.java +++ b/src/main/java/dan200/computercraft/api/network/IPacketReceiver.java @@ -6,15 +6,16 @@ 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. * @@ -59,25 +60,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. + * 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 ); } diff --git a/src/main/java/dan200/computercraft/api/network/IPacketSender.java b/src/main/java/dan200/computercraft/api/network/IPacketSender.java index c5e15a06d..f3c06a397 100644 --- a/src/main/java/dan200/computercraft/api/network/IPacketSender.java +++ b/src/main/java/dan200/computercraft/api/network/IPacketSender.java @@ -6,15 +6,16 @@ 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. * diff --git a/src/main/java/dan200/computercraft/api/network/Packet.java b/src/main/java/dan200/computercraft/api/network/Packet.java index a15c4f9a7..58251e01f 100644 --- a/src/main/java/dan200/computercraft/api/network/Packet.java +++ b/src/main/java/dan200/computercraft/api/network/Packet.java @@ -6,10 +6,9 @@ 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}. @@ -20,7 +19,8 @@ import javax.annotation.Nullable; * @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; @@ -30,14 +30,15 @@ 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; @@ -50,7 +51,8 @@ public class Packet { * * @return This packet's channel. */ - public int getChannel() { + public int getChannel() + { return this.channel; } @@ -59,7 +61,8 @@ public class Packet { * * @return This channel to reply on. */ - public int getReplyChannel() { + public int getReplyChannel() + { return this.replyChannel; } @@ -69,7 +72,8 @@ public class Packet { * @return The packet's payload */ @Nullable - public Object getPayload() { + public Object getPayload() + { return this.payload; } @@ -79,12 +83,14 @@ public class Packet { * @return The sending object. */ @Nonnull - public IPacketSender getSender() { + public IPacketSender getSender() + { return this.sender; } @Override - public int hashCode() { + public int hashCode() + { int result; result = this.channel; result = 31 * result + this.replyChannel; @@ -94,25 +100,31 @@ public class Packet { } @Override - public boolean equals(Object o) { - if (this == o) { + public boolean equals( Object o ) + { + if( this == o ) + { return true; } - if (o == null || this.getClass() != o.getClass()) { + if( o == null || this.getClass() != o.getClass() ) + { return false; } Packet packet = (Packet) o; - if (this.channel != packet.channel) { + if( this.channel != packet.channel ) + { return false; } - if (this.replyChannel != packet.replyChannel) { + if( this.replyChannel != packet.replyChannel ) + { return false; } - if (!Objects.equals(this.payload, packet.payload)) { + if( !Objects.equals( this.payload, packet.payload ) ) + { return false; } - return this.sender.equals(packet.sender); + return this.sender.equals( packet.sender ); } } diff --git a/src/main/java/dan200/computercraft/api/network/wired/IWiredElement.java b/src/main/java/dan200/computercraft/api/network/wired/IWiredElement.java index f4d4daaf1..5ca0ddb9f 100644 --- a/src/main/java/dan200/computercraft/api/network/wired/IWiredElement.java +++ b/src/main/java/dan200/computercraft/api/network/wired/IWiredElement.java @@ -6,10 +6,10 @@ package dan200.computercraft.api.network.wired; -import javax.annotation.Nonnull; - import dan200.computercraft.api.ComputerCraftAPI; +import javax.annotation.Nonnull; + /** * An object which may be part of a wired network. * @@ -19,13 +19,15 @@ import dan200.computercraft.api.ComputerCraftAPI; * 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. * * @param change The change which occurred. * @see IWiredNetworkChange */ - default void networkChanged(@Nonnull IWiredNetworkChange change) { + default void networkChanged( @Nonnull IWiredNetworkChange change ) + { } } diff --git a/src/main/java/dan200/computercraft/api/network/wired/IWiredNetwork.java b/src/main/java/dan200/computercraft/api/network/wired/IWiredNetwork.java index dc7dac86f..fa44c4d1b 100644 --- a/src/main/java/dan200/computercraft/api/network/wired/IWiredNetwork.java +++ b/src/main/java/dan200/computercraft/api/network/wired/IWiredNetwork.java @@ -6,11 +6,10 @@ package dan200.computercraft.api.network.wired; -import java.util.Map; +import dan200.computercraft.api.peripheral.IPeripheral; import javax.annotation.Nonnull; - -import dan200.computercraft.api.peripheral.IPeripheral; +import java.util.Map; /** * A wired network is composed of one of more {@link IWiredNode}s, a set of connections between them, and a series of peripherals. @@ -24,28 +23,29 @@ import dan200.computercraft.api.peripheral.IPeripheral; * * @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. @@ -53,7 +53,7 @@ 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. @@ -65,17 +65,17 @@ public interface IWiredNetwork { * @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. * - * @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 peripherals); + void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map peripherals ); } diff --git a/src/main/java/dan200/computercraft/api/network/wired/IWiredNetworkChange.java b/src/main/java/dan200/computercraft/api/network/wired/IWiredNetworkChange.java index 4f9428427..bef4b1048 100644 --- a/src/main/java/dan200/computercraft/api/network/wired/IWiredNetworkChange.java +++ b/src/main/java/dan200/computercraft/api/network/wired/IWiredNetworkChange.java @@ -6,18 +6,18 @@ package dan200.computercraft.api.network.wired; -import java.util.Map; +import dan200.computercraft.api.peripheral.IPeripheral; import javax.annotation.Nonnull; - -import dan200.computercraft.api.peripheral.IPeripheral; +import java.util.Map; /** * 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. diff --git a/src/main/java/dan200/computercraft/api/network/wired/IWiredNode.java b/src/main/java/dan200/computercraft/api/network/wired/IWiredNode.java index c4fa6d4c0..233da434c 100644 --- a/src/main/java/dan200/computercraft/api/network/wired/IWiredNode.java +++ b/src/main/java/dan200/computercraft/api/network/wired/IWiredNode.java @@ -6,13 +6,12 @@ package dan200.computercraft.api.network.wired; -import java.util.Map; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.network.IPacketNetwork; import dan200.computercraft.api.peripheral.IPeripheral; +import javax.annotation.Nonnull; +import java.util.Map; + /** * Wired nodes act as a layer between {@link IWiredElement}s and {@link IWiredNetwork}s. * @@ -25,7 +24,8 @@ import dan200.computercraft.api.peripheral.IPeripheral; * * 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. * @@ -44,8 +44,9 @@ public interface IWiredNode extends IPacketNetwork { * @see IWiredNetwork#connect(IWiredNode, IWiredNode) * @see IWiredNode#disconnectFrom(IWiredNode) */ - default boolean connectTo(@Nonnull IWiredNode node) { - return this.getNetwork().connect(this, node); + default boolean connectTo( @Nonnull IWiredNode node ) + { + return this.getNetwork().connect( this, node ); } /** @@ -69,8 +70,9 @@ public interface IWiredNode extends IPacketNetwork { * @see IWiredNetwork#disconnect(IWiredNode, IWiredNode) * @see IWiredNode#connectTo(IWiredNode) */ - default boolean disconnectFrom(@Nonnull IWiredNode node) { - return this.getNetwork().disconnect(this, node); + default boolean disconnectFrom( @Nonnull IWiredNode node ) + { + return this.getNetwork().disconnect( this, node ); } /** @@ -82,8 +84,9 @@ public interface IWiredNode extends IPacketNetwork { * @throws IllegalArgumentException If the node is not in the network. * @see IWiredNetwork#remove(IWiredNode) */ - default boolean remove() { - return this.getNetwork().remove(this); + default boolean remove() + { + return this.getNetwork().remove( this ); } /** @@ -94,7 +97,8 @@ public interface IWiredNode extends IPacketNetwork { * @param peripherals The new peripherals for this node. * @see IWiredNetwork#updatePeripherals(IWiredNode, Map) */ - default void updatePeripherals(@Nonnull Map peripherals) { - this.getNetwork().updatePeripherals(this, peripherals); + default void updatePeripherals( @Nonnull Map peripherals ) + { + this.getNetwork().updatePeripherals( this, peripherals ); } } diff --git a/src/main/java/dan200/computercraft/api/network/wired/IWiredSender.java b/src/main/java/dan200/computercraft/api/network/wired/IWiredSender.java index e03ee5df1..c306b0a6b 100644 --- a/src/main/java/dan200/computercraft/api/network/wired/IWiredSender.java +++ b/src/main/java/dan200/computercraft/api/network/wired/IWiredSender.java @@ -6,16 +6,17 @@ package dan200.computercraft.api.network.wired; -import javax.annotation.Nonnull; - import dan200.computercraft.api.network.IPacketSender; +import javax.annotation.Nonnull; + /** * 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. */ -public interface IWiredSender extends IPacketSender { +public interface IWiredSender extends IPacketSender +{ /** * The node in the network representing this object. * diff --git a/src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java b/src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java index 732266ec1..30d4c6522 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java @@ -6,11 +6,6 @@ package dan200.computercraft.api.peripheral; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; @@ -18,21 +13,25 @@ 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; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Map; + /** * 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. + * @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. + * 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(String, String) @@ -42,18 +41,19 @@ public interface IComputerAccess { * @see IMount */ @Nullable - default String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) { - return this.mount(desiredLocation, mount, this.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()}. + * @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. + * 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(String, String) @@ -63,7 +63,7 @@ public interface IComputerAccess { * @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 @@ -80,9 +80,9 @@ public interface IComputerAccess { * 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 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. + * 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(String, String) @@ -91,18 +91,19 @@ public interface IComputerAccess { * @see IMount */ @Nullable - default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritableMount mount) { - return this.mountWritable(desiredLocation, mount, this.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()}. + * @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. + * 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(String, String) @@ -110,7 +111,7 @@ public interface IComputerAccess { * @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, @@ -122,13 +123,13 @@ public interface IComputerAccess { * 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 NotAttachedException If the peripheral has been detached. + * 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. @@ -144,17 +145,17 @@ public interface IComputerAccess { * 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 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(). + * 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. + * 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); + void queueEvent( @Nonnull String event, @Nullable Object... arguments ); /** * Get a set of peripherals that this computer access can "see", along with their attachment name. @@ -178,7 +179,7 @@ public interface IComputerAccess { * @see #getAvailablePeripherals() */ @Nullable - IPeripheral getAvailablePeripheral(@Nonnull String name); + IPeripheral getAvailablePeripheral( @Nonnull String name ); /** * Get a {@link IWorkMonitor} for tasks your peripheral might execute on the main (server) thread. diff --git a/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java b/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java index 9842600dc..e06c14096 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java @@ -6,14 +6,9 @@ package dan200.computercraft.api.peripheral; -import javax.annotation.Nonnull; +import dan200.computercraft.api.lua.*; -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; +import javax.annotation.Nonnull; /** * A peripheral whose methods are not known at runtime. @@ -21,7 +16,8 @@ import dan200.computercraft.api.lua.MethodResult; * 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 { +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. @@ -38,16 +34,16 @@ public interface IDynamicPeripheral extends IPeripheral { * * 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 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. + * 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; + MethodResult callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments ) throws LuaException; } diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java index 73e7a04d6..09a63c64d 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java @@ -6,11 +6,11 @@ package dan200.computercraft.api.peripheral; +import dan200.computercraft.api.lua.LuaFunction; + import javax.annotation.Nonnull; import javax.annotation.Nullable; -import dan200.computercraft.api.lua.LuaFunction; - /** * The interface that defines a peripheral. * @@ -19,7 +19,8 @@ import dan200.computercraft.api.lua.LuaFunction; * * 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()} * @@ -42,7 +43,8 @@ public interface IPeripheral { * @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 ) + { } /** @@ -58,7 +60,8 @@ public interface IPeripheral { * @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 ) + { } /** @@ -67,7 +70,8 @@ public interface IPeripheral { * @return The object this peripheral targets */ @Nullable - default Object getTarget() { + default Object getTarget() + { return null; } @@ -80,5 +84,5 @@ public interface IPeripheral { * @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 ); } diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java index 5697ad681..ae704dfc7 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java @@ -6,15 +6,14 @@ package dan200.computercraft.api.peripheral; -import java.util.Optional; - -import javax.annotation.Nonnull; - import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; +import javax.annotation.Nonnull; +import java.util.Optional; + /** * This interface is used to create peripheral implementations for blocks. * @@ -23,16 +22,17 @@ import net.minecraft.world.World; * @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. + * @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) */ @Nonnull - IPeripheral getPeripheral(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side); + IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); } diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java index 4b463dc1b..b12d7f5c0 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralTile.java @@ -5,19 +5,20 @@ */ 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; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * 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 { +public interface IPeripheralTile +{ /** * Get the peripheral on the given {@code side}. * @@ -26,5 +27,5 @@ public interface IPeripheralTile { * @see IPeripheralProvider#getPeripheral(World, BlockPos, Direction) */ @Nullable - IPeripheral getPeripheral(@Nonnull Direction side); + IPeripheral getPeripheral( @Nonnull Direction side ); } diff --git a/src/main/java/dan200/computercraft/api/peripheral/IWorkMonitor.java b/src/main/java/dan200/computercraft/api/peripheral/IWorkMonitor.java index 22b0863f6..bddfb4985 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IWorkMonitor.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IWorkMonitor.java @@ -6,11 +6,10 @@ package dan200.computercraft.api.peripheral; +import javax.annotation.Nonnull; 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. @@ -25,7 +24,8 @@ import javax.annotation.Nonnull; * * @see IComputerAccess#getMainThreadMonitor() */ -public interface IWorkMonitor { +public interface IWorkMonitor +{ /** * If the owning computer is currently allowed to execute work, and has ample time to do so. * @@ -42,17 +42,22 @@ public interface IWorkMonitor { * @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()) { + default boolean runWork( @Nonnull Runnable runnable ) + { + Objects.requireNonNull( runnable, "runnable should not be null" ); + if( !this.canWork() ) + { return false; } long start = System.nanoTime(); - try { + try + { runnable.run(); - } finally { - this.trackWork(System.nanoTime() - start, TimeUnit.NANOSECONDS); + } + finally + { + this.trackWork( System.nanoTime() - start, TimeUnit.NANOSECONDS ); } return true; @@ -71,5 +76,5 @@ public interface IWorkMonitor { * @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); + void trackWork( long time, @Nonnull TimeUnit unit ); } diff --git a/src/main/java/dan200/computercraft/api/peripheral/NotAttachedException.java b/src/main/java/dan200/computercraft/api/peripheral/NotAttachedException.java index 4690c9b3a..335841cfb 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/NotAttachedException.java +++ b/src/main/java/dan200/computercraft/api/peripheral/NotAttachedException.java @@ -9,14 +9,17 @@ 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 { +public class NotAttachedException extends IllegalStateException +{ private static final long serialVersionUID = 1221244785535553536L; - public NotAttachedException() { - super("You are not attached to this computer"); + public NotAttachedException() + { + super( "You are not attached to this computer" ); } - public NotAttachedException(String s) { - super(s); + public NotAttachedException( String s ) + { + super( s ); } } diff --git a/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java b/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java index 9e6ca54c1..16f183441 100644 --- a/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java +++ b/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java @@ -6,34 +6,38 @@ 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; +import javax.annotation.Nonnull; + /** * 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 { +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, ItemConvertible item ) + { + this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item ); } - protected AbstractPocketUpgrade(Identifier id, String adjective, ItemConvertible item) { + protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item ) + { this.id = id; this.adjective = adjective; - this.stack = new ItemStack(item); + this.stack = new ItemStack( item ); } - protected AbstractPocketUpgrade(Identifier id, String adjective, ItemStack stack) { + protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack ) + { this.id = id; this.adjective = adjective; this.stack = stack; @@ -42,19 +46,22 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade { @Nonnull @Override - public final Identifier getUpgradeID() { + public final Identifier getUpgradeID() + { return this.id; } @Nonnull @Override - public final String getUnlocalisedAdjective() { + public final String getUnlocalisedAdjective() + { return this.adjective; } @Nonnull @Override - public final ItemStack getCraftingItem() { + public final ItemStack getCraftingItem() + { return this.stack; } } diff --git a/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java b/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java index 792703fc9..fe82eb5ab 100644 --- a/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java +++ b/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java @@ -6,21 +6,20 @@ package dan200.computercraft.api.pocket; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.peripheral.IPeripheral; - import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Identifier; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Map; + /** * Wrapper class for pocket computers. */ -public interface IPocketAccess { +public interface IPocketAccess +{ /** * Gets the entity holding this item. * @@ -43,10 +42,10 @@ 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. + * -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. @@ -60,10 +59,10 @@ 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. + * to reset to the default colour. * @see #getLight() */ - void setLight(int colour); + void setLight( int colour ); /** * Get the upgrade-specific NBT. diff --git a/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java b/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java index a9e9c8517..d8b9d0c13 100644 --- a/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java +++ b/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java @@ -6,15 +6,14 @@ package dan200.computercraft.api.pocket; -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; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Additional peripherals for pocket computers. * @@ -33,29 +32,31 @@ public interface IPocketUpgrade extends IUpgradeBase * @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. + * 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; } } diff --git a/src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java b/src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java index 90f00db0f..ad92f3903 100644 --- a/src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java +++ b/src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java @@ -6,27 +6,28 @@ package dan200.computercraft.api.redstone; -import javax.annotation.Nonnull; - import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; +import javax.annotation.Nonnull; + /** * 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. + * @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 Direction side); + int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); } diff --git a/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java b/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java index d099f6148..34b5bc1cf 100644 --- a/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java +++ b/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java @@ -6,65 +6,74 @@ 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; +import javax.annotation.Nonnull; + /** * 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 { +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, ItemConvertible item ) + { + this( id, type, adjective, new ItemStack( item ) ); } - protected AbstractTurtleUpgrade(Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack) { + 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, 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); + protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack ) + { + this( id, type, Util.createTranslationKey( "upgrade", id ) + ".adjective", stack ); } @Nonnull @Override - public final Identifier getUpgradeID() { + public final Identifier getUpgradeID() + { return this.id; } @Nonnull @Override - public final String getUnlocalisedAdjective() { + public final String getUnlocalisedAdjective() + { return this.adjective; } @Nonnull @Override - public final TurtleUpgradeType getType() { + public final TurtleUpgradeType getType() + { return this.type; } @Nonnull @Override - public final ItemStack getCraftingItem() { + public final ItemStack getCraftingItem() + { return this.stack; } } diff --git a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java index 7c17ad6a2..f1cfd1790 100644 --- a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java +++ b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java @@ -5,18 +5,10 @@ */ 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; @@ -26,11 +18,7 @@ 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.*; import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket; import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; import net.minecraft.recipe.Recipe; @@ -50,15 +38,23 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.village.TradeOfferList; import net.minecraft.world.GameMode; +import javax.annotation.Nullable; +import javax.crypto.Cipher; +import java.util.Collection; +import java.util.OptionalInt; +import java.util.UUID; + /** * 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); +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 @@ -75,20 +71,23 @@ public class FakePlayer extends ServerPlayerEntity { public void playerTick() { } @Override - public void onDeath(DamageSource damage) { } + public void onDeath( DamageSource damage ) { } @Override - public Entity moveToWorld(ServerWorld destination) { + public Entity moveToWorld( ServerWorld destination ) + { return this; } @Override - public void wakeUp(boolean bl, boolean updateSleepingPlayers) { + public void wakeUp( boolean bl, boolean updateSleepingPlayers ) + { } @Override - public boolean startRiding(Entity entity, boolean flag) { + public boolean startRiding( Entity entity, boolean flag ) + { return false; } @@ -96,33 +95,34 @@ public class FakePlayer extends ServerPlayerEntity { public void stopRiding() { } @Override - public void openEditSignScreen(SignBlockEntity tile) { } + public void openEditSignScreen( SignBlockEntity tile ) { } @Override - public OptionalInt openHandledScreen(@Nullable NamedScreenHandlerFactory container) { + 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) { } + public void sendTradeOffers( int id, TradeOfferList list, int level, int experience, boolean levelled, boolean refreshable ) { } @Override - public void openHorseInventory(HorseBaseEntity horse, Inventory inventory) { } + public void openHorseInventory( HorseBaseEntity horse, Inventory inventory ) { } @Override - public void openEditBookScreen(ItemStack stack, Hand hand) { } + public void openEditBookScreen( ItemStack stack, Hand hand ) { } @Override - public void openCommandBlockScreen(CommandBlockBlockEntity block) { } + public void openCommandBlockScreen( CommandBlockBlockEntity block ) { } @Override - public void onSlotUpdate(ScreenHandler container, int slot, ItemStack stack) { } + public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack ) { } @Override - public void onHandlerRegistered(ScreenHandler container, DefaultedList defaultedList) { } + public void onHandlerRegistered( ScreenHandler container, DefaultedList defaultedList ) { } @Override - public void onPropertyUpdate(ScreenHandler container, int key, int value) { } + public void onPropertyUpdate( ScreenHandler container, int key, int value ) { } @Override public void closeHandledScreen() { } @@ -131,136 +131,154 @@ public class FakePlayer extends ServerPlayerEntity { public void updateCursorStack() { } @Override - public int unlockRecipes(Collection> recipes) { + public int unlockRecipes( Collection> recipes ) + { return 0; } // Indirect @Override - public int lockRecipes(Collection> recipes) { + public int lockRecipes( Collection> recipes ) + { return 0; } @Override - public void sendMessage(Text textComponent, boolean status) { } + public void sendMessage( Text textComponent, boolean status ) { } @Override protected void consumeItem() { } @Override - public void lookAt(EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d) {} + public void lookAt( EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d ) {} @Override - public void method_14222(EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target) { } + public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) { } @Override - protected void onStatusEffectApplied(StatusEffectInstance statusEffectInstance) { } + protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance ) { } @Override - protected void onStatusEffectUpgraded(StatusEffectInstance statusEffectInstance, boolean particles) { } + protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles ) { } @Override - protected void onStatusEffectRemoved(StatusEffectInstance statusEffectInstance) { } + protected void onStatusEffectRemoved( StatusEffectInstance statusEffectInstance ) { } @Override - public void requestTeleport(double x, double y, double z) { } + public void requestTeleport( double x, double y, double z ) { } @Override - public void setGameMode(GameMode gameMode) { } + public void setGameMode( GameMode gameMode ) { } @Override - public void sendMessage(Text message, MessageType type, UUID senderUuid) { + public void sendMessage( Text message, MessageType type, UUID senderUuid ) + { } @Override - public String getIp() { + public String getIp() + { return "[Fake Player]"; } @Override - public void sendResourcePackUrl(String url, String hash) { } + public void sendResourcePackUrl( String url, String hash ) { } @Override - public void onStoppedTracking(Entity entity) { } + public void onStoppedTracking( Entity entity ) { } @Override - public void setCameraEntity(Entity entity) { } + public void setCameraEntity( Entity entity ) { } @Override - public void teleport(ServerWorld serverWorld, double x, double y, double z, float pitch, float yaw) { } + 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) { } + public void sendInitialChunkPackets( ChunkPos chunkPos, Packet packet, Packet packet2 ) { } @Override - public void sendUnloadChunkPacket(ChunkPos chunkPos) { } + public void sendUnloadChunkPacket( ChunkPos chunkPos ) { } @Override - public void playSound(SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch) { } + 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); + private static class FakeNetHandler extends ServerPlayNetworkHandler + { + FakeNetHandler( ServerPlayerEntity player ) + { + super( player.server, new FakeConnection(), player ); } @Override - public void disconnect(Text message) { } + public void disconnect( Text message ) { } @Override - public void onVehicleMove(VehicleMoveC2SPacket move) { } + public void onVehicleMove( VehicleMoveC2SPacket move ) { } @Override - public void onRequestCommandCompletions(RequestCommandCompletionsC2SPacket packet) { } + public void onRequestCommandCompletions( RequestCommandCompletionsC2SPacket packet ) { } @Override - public void sendPacket(Packet packet, @Nullable GenericFutureListener> listener) { } + public void sendPacket( Packet packet, @Nullable GenericFutureListener> listener ) { } } - private static class FakeConnection extends ClientConnection { - FakeConnection() { - super(NetworkSide.CLIENTBOUND); + private static class FakeConnection extends ClientConnection + { + FakeConnection() + { + super( NetworkSide.CLIENTBOUND ); } @Override - public void channelActive(ChannelHandlerContext active) { + public void channelActive( ChannelHandlerContext active ) + { } @Override - public void setState(NetworkState state) { + public void setState( NetworkState state ) + { } @Override - public void exceptionCaught(ChannelHandlerContext context, Throwable err) { + public void exceptionCaught( ChannelHandlerContext context, Throwable err ) + { } @Override - protected void channelRead0(ChannelHandlerContext context, Packet packet) { + protected void channelRead0( ChannelHandlerContext context, Packet packet ) + { } @Override - public void send(Packet packet, @Nullable GenericFutureListener> listener) { + public void send( Packet packet, @Nullable GenericFutureListener> listener ) + { } @Override - public void tick() { + public void tick() + { } @Override - public void disconnect(Text message) { + public void disconnect( Text message ) + { } @Override - public void setupEncryption(Cipher cipher, Cipher cipher2) { - super.setupEncryption(cipher, cipher2); + public void setupEncryption( Cipher cipher, Cipher cipher2 ) + { + super.setupEncryption( cipher, cipher2 ); } @Override - public void disableAutoRead() { + public void disableAutoRead() + { } @Override - public void setCompressionThreshold(int size) { + public void setCompressionThreshold( int size ) + { } } } diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java index f7edbbe7d..14c96c638 100644 --- a/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java @@ -6,15 +6,11 @@ package dan200.computercraft.api.turtle; -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; @@ -22,12 +18,16 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * 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}. */ -public interface ITurtleAccess { +public interface ITurtleAccess +{ /** * Returns the world in which the turtle resides. * @@ -51,11 +51,11 @@ public interface ITurtleAccess { * using {@link #playAnimation(TurtleAnimation)}. * * @param world The new world to move it to - * @param pos The new position 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. * @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. @@ -65,7 +65,7 @@ public interface ITurtleAccess { * @see #getVisualYaw(float) */ @Nonnull - Vec3d getVisualPosition(float f); + Vec3d getVisualPosition( float f ); /** * Returns the yaw the turtle is facing when it is rendered. @@ -74,7 +74,7 @@ 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. @@ -92,7 +92,7 @@ public interface ITurtleAccess { * @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 Direction dir); + void setDirection( @Nonnull Direction dir ); /** * Get the currently selected slot in the turtle's inventory. @@ -111,7 +111,7 @@ public interface ITurtleAccess { * @see #getInventory() * @see #getSelectedSlot() */ - void setSelectedSlot(int slot); + void setSelectedSlot( int slot ); /** * Get the colour of this turtle as a RGB number. @@ -125,10 +125,10 @@ public interface ITurtleAccess { * 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. + * reset to the default colour. * @see #getColour() */ - void setColour(int colour); + void setColour( int colour ); /** * Get the player who owns this turtle, namely whoever placed it. @@ -165,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. @@ -179,10 +179,10 @@ public interface ITurtleAccess { * * @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. + * 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. @@ -190,7 +190,7 @@ 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 @@ -205,7 +205,7 @@ public interface ITurtleAccess { * @see MethodResult#pullEvent(String, ILuaCallback) */ @Nonnull - MethodResult executeCommand(@Nonnull ITurtleCommand command); + MethodResult executeCommand( @Nonnull ITurtleCommand command ); /** * Start playing a specific animation. This will prevent other turtle commands from executing until it is finished. @@ -214,7 +214,7 @@ public interface ITurtleAccess { * @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. @@ -224,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. @@ -242,7 +242,7 @@ 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. @@ -255,7 +255,7 @@ public interface ITurtleAccess { * @see #updateUpgradeNBTData(TurtleSide) */ @Nonnull - CompoundTag 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. @@ -263,10 +263,11 @@ public interface ITurtleAccess { * @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()); + default ItemStorage getItemHandler() + { + return ItemStorage.wrap( this.getInventory() ); } /** diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java index 12babcf33..134bb346d 100644 --- a/src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java @@ -14,7 +14,8 @@ import javax.annotation.Nonnull; * @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. * @@ -29,5 +30,5 @@ public interface ITurtleCommand { * @see TurtleCommandResult */ @Nonnull - TurtleCommandResult execute(@Nonnull ITurtleAccess turtle); + TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ); } diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java index 0ba94365e..bc9d9e018 100644 --- a/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java @@ -6,18 +6,16 @@ package dan200.computercraft.api.turtle; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - 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; +import net.minecraft.util.math.Direction; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * The primary interface for defining an update for Turtles. A turtle update can either be a new tool, or a new peripheral. @@ -42,28 +40,30 @@ public interface ITurtleUpgrade extends IUpgradeBase * 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. + * @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. * - * @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 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. + * 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. + * 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 Direction direction) { + default TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) + { return TurtleCommandResult.failure(); } @@ -71,19 +71,20 @@ public interface ITurtleUpgrade extends IUpgradeBase * Called to obtain the model to be used when rendering a turtle peripheral. * * @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. + * @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 - @Environment (EnvType.CLIENT) - TransformedModel 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 ) + { } } diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java b/src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java index 4b7efa9de..f4468b5c9 100644 --- a/src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java @@ -13,7 +13,8 @@ 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. * diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java b/src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java index 6d0d569ea..70974fc24 100644 --- a/src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java @@ -15,14 +15,16 @@ import javax.annotation.Nullable; * @see ITurtleCommand#execute(ITurtleAccess) * @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) { + private TurtleCommandResult( boolean success, String errorMessage, Object[] results ) + { this.success = success; this.errorMessage = errorMessage; this.results = results; @@ -34,7 +36,8 @@ public final class TurtleCommandResult { * @return A successful command result with no values. */ @Nonnull - public static TurtleCommandResult success() { + public static TurtleCommandResult success() + { return EMPTY_SUCCESS; } @@ -45,11 +48,13 @@ 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) { + public static TurtleCommandResult success( @Nullable Object[] results ) + { + if( results == null || results.length == 0 ) + { return EMPTY_SUCCESS; } - return new TurtleCommandResult(true, null, results); + return new TurtleCommandResult( true, null, results ); } /** @@ -58,7 +63,8 @@ public final class TurtleCommandResult { * @return A failed command result with no message. */ @Nonnull - public static TurtleCommandResult failure() { + public static TurtleCommandResult failure() + { return EMPTY_FAILURE; } @@ -69,11 +75,13 @@ public final class TurtleCommandResult { * @return A failed command result with a message. */ @Nonnull - public static TurtleCommandResult failure(@Nullable String errorMessage) { - if (errorMessage == null) { + public static TurtleCommandResult failure( @Nullable String errorMessage ) + { + if( errorMessage == null ) + { return EMPTY_FAILURE; } - return new TurtleCommandResult(false, errorMessage, null); + return new TurtleCommandResult( false, errorMessage, null ); } /** @@ -81,7 +89,8 @@ public final class TurtleCommandResult { * * @return If the command was successful. */ - public boolean isSuccess() { + public boolean isSuccess() + { return this.success; } @@ -91,7 +100,8 @@ public final class TurtleCommandResult { * @return The command's error message, or {@code null} if it was a success. */ @Nullable - public String getErrorMessage() { + public String getErrorMessage() + { return this.errorMessage; } @@ -101,7 +111,8 @@ public final class TurtleCommandResult { * @return The command's result, or {@code null} if it was a failure. */ @Nullable - public Object[] getResults() { + public Object[] getResults() + { return this.results; } } diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleSide.java b/src/main/java/dan200/computercraft/api/turtle/TurtleSide.java index be448090a..86edade62 100644 --- a/src/main/java/dan200/computercraft/api/turtle/TurtleSide.java +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleSide.java @@ -9,7 +9,8 @@ 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). */ diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java b/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java index 6ac4537e0..a6c6fede4 100644 --- a/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java @@ -11,7 +11,8 @@ 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). @@ -30,11 +31,13 @@ public enum TurtleUpgradeType { */ BOTH; - public boolean isTool() { + public boolean isTool() + { return this == TOOL || this == BOTH; } - public boolean isPeripheral() { + public boolean isPeripheral() + { return this == PERIPHERAL || this == BOTH; } } diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java b/src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java index c057bdc1d..d4622b1a0 100644 --- a/src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java @@ -12,7 +12,8 @@ package dan200.computercraft.api.turtle; * @see ITurtleUpgrade#getType() * @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()}. */ diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleAction.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleAction.java index d3397af67..ca5ccecf6 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleAction.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleAction.java @@ -11,7 +11,8 @@ package dan200.computercraft.api.turtle.event; * * @see TurtleActionEvent */ -public enum TurtleAction { +public enum TurtleAction +{ /** * A turtle moves to a new position. * diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleActionEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleActionEvent.java index e336b7606..ac1e93952 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleActionEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleActionEvent.java @@ -6,30 +6,32 @@ package dan200.computercraft.api.turtle.event; -import java.util.Objects; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.TurtleCommandResult; import javax.annotation.Nonnull; import javax.annotation.Nullable; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleCommandResult; +import java.util.Objects; /** * An event fired when a turtle is performing a known action. */ -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() { + public TurtleAction getAction() + { return this.action; } @@ -43,8 +45,9 @@ public class TurtleActionEvent extends TurtleEvent { * @deprecated Use {@link #setCanceled(boolean, String)} instead. */ @Deprecated - public void setCanceled(boolean cancel) { - this.setCanceled(cancel, null); + public void setCanceled( boolean cancel ) + { + this.setCanceled( cancel, null ); } /** @@ -52,11 +55,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) { + public void setCanceled( boolean cancel, @Nullable String failureMessage ) + { this.cancelled = true; this.failureMessage = cancel ? failureMessage : null; } @@ -69,11 +73,13 @@ public class TurtleActionEvent extends TurtleEvent { * @see #setCanceled(boolean, String) */ @Nullable - public String getFailureMessage() { + public String getFailureMessage() + { return this.failureMessage; } - public boolean isCancelled() { + public boolean isCancelled() + { return this.cancelled; } } diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleAttackEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleAttackEvent.java index dc5ab0cc7..4a8440d39 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleAttackEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleAttackEvent.java @@ -6,33 +6,33 @@ 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 net.minecraft.entity.Entity; +import javax.annotation.Nonnull; +import java.util.Objects; + /** * Fired when a turtle attempts to attack an entity. * * @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; @@ -44,7 +44,8 @@ public class TurtleAttackEvent extends TurtlePlayerEvent { * @return The entity being attacked. */ @Nonnull - public Entity getTarget() { + public Entity getTarget() + { return this.target; } @@ -54,7 +55,8 @@ public class TurtleAttackEvent extends TurtlePlayerEvent { * @return The upgrade responsible for attacking. */ @Nonnull - public ITurtleUpgrade getUpgrade() { + public ITurtleUpgrade getUpgrade() + { return this.upgrade; } @@ -64,7 +66,8 @@ public class TurtleAttackEvent extends TurtlePlayerEvent { * @return The upgrade's side. */ @Nonnull - public TurtleSide getSide() { + public TurtleSide getSide() + { return this.side; } } diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleBlockEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleBlockEvent.java index 59987558e..1b8ded608 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleBlockEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleBlockEvent.java @@ -6,22 +6,20 @@ 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.FakePlayer; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; - import net.minecraft.block.BlockState; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +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. * @@ -31,16 +29,18 @@ import net.minecraft.world.World; * * Be aware that some events (such as {@link TurtleInventoryEvent}) do not necessarily interact with a block, simply objects within that block space. */ -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; } @@ -50,7 +50,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * * @return The world the turtle is interacting in. */ - public World getWorld() { + public World getWorld() + { return this.world; } @@ -59,7 +60,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * * @return The position the turtle is interacting with. */ - public BlockPos getPos() { + public BlockPos getPos() + { return this.pos; } @@ -68,18 +70,20 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * * @see TurtleAction#DIG */ - public static class Dig extends TurtleBlockEvent { + 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 BlockState 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; @@ -91,7 +95,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * @return The block which is going to be broken. */ @Nonnull - public BlockState getBlock() { + public BlockState getBlock() + { return this.block; } @@ -101,7 +106,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * @return The upgrade doing the digging. */ @Nonnull - public ITurtleUpgrade getUpgrade() { + public ITurtleUpgrade getUpgrade() + { return this.upgrade; } @@ -111,7 +117,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * @return The upgrade's side. */ @Nonnull - public TurtleSide getSide() { + public TurtleSide getSide() + { return this.side; } } @@ -121,9 +128,11 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * * @see TurtleAction#MOVE */ - 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 ); } } @@ -132,13 +141,15 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * * @see TurtleAction#PLACE */ - 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; } @@ -148,7 +159,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * @return The item stack to be placed. */ @Nonnull - public ItemStack getStack() { + public ItemStack getStack() + { return this.stack; } } @@ -160,16 +172,18 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * * @see TurtleAction#INSPECT */ - public static class Inspect extends TurtleBlockEvent { + public static class Inspect extends TurtleBlockEvent + { private final BlockState state; private final Map data; - public Inspect(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, - @Nonnull Map 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 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; } @@ -180,7 +194,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * @return The inspected block state. */ @Nonnull - public BlockState getState() { + public BlockState getState() + { return this.state; } @@ -190,7 +205,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * @return This block's inspection data. */ @Nonnull - public Map getData() { + public Map getData() + { return this.data; } @@ -199,9 +215,10 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent { * * @param newData The data to add. Note all values should be convertible to Lua (see {@link MethodResult#of(Object)}). */ - public void addData(@Nonnull Map newData) { - Objects.requireNonNull(newData, "newData cannot be null"); - this.data.putAll(newData); + public void addData( @Nonnull Map newData ) + { + Objects.requireNonNull( newData, "newData cannot be null" ); + this.data.putAll( newData ); } } } diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleEvent.java index ee3a63318..7d11a1432 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleEvent.java @@ -6,13 +6,12 @@ package dan200.computercraft.api.turtle.event; -import java.util.Objects; - -import javax.annotation.Nonnull; - import com.google.common.eventbus.EventBus; import dan200.computercraft.api.turtle.ITurtleAccess; +import javax.annotation.Nonnull; +import java.util.Objects; + /** * 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. @@ -21,18 +20,21 @@ import dan200.computercraft.api.turtle.ITurtleAccess; * * @see TurtleActionEvent */ -public abstract class TurtleEvent { +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); + public static boolean post( TurtleActionEvent event ) + { + EVENT_BUS.post( event ); return event.isCancelled(); } @@ -42,7 +44,8 @@ public abstract class TurtleEvent { * @return The access for this turtle. */ @Nonnull - public ITurtleAccess getTurtle() { + public ITurtleAccess getTurtle() + { return this.turtle; } diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleInspectItemEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleInspectItemEvent.java index 183431e5e..3da00d484 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleInspectItemEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleInspectItemEvent.java @@ -6,16 +6,14 @@ 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; +import javax.annotation.Nonnull; +import java.util.Map; +import java.util.Objects; + /** * Fired when a turtle gathers data on an item in its inventory. * @@ -24,21 +22,24 @@ import net.minecraft.item.ItemStack; * * @see TurtleAction#INSPECT_ITEM */ -public class TurtleInspectItemEvent extends TurtleActionEvent { +public class TurtleInspectItemEvent extends TurtleActionEvent +{ private final ItemStack stack; private final Map data; private final boolean mainThread; @Deprecated - public TurtleInspectItemEvent(@Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map data) { - this(turtle, stack, data, false); + public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map data ) + { + this( turtle, stack, data, false ); } - public TurtleInspectItemEvent(@Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map data, boolean mainThread) { - super(turtle, TurtleAction.INSPECT_ITEM); + public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map data, boolean mainThread ) + { + super( turtle, TurtleAction.INSPECT_ITEM ); - Objects.requireNonNull(stack, "stack cannot be null"); - Objects.requireNonNull(data, "data cannot be null"); + Objects.requireNonNull( stack, "stack cannot be null" ); + Objects.requireNonNull( data, "data cannot be null" ); this.stack = stack; this.data = data; this.mainThread = mainThread; @@ -50,7 +51,8 @@ public class TurtleInspectItemEvent extends TurtleActionEvent { * @return The item stack which is being inspected. This should not be modified. */ @Nonnull - public ItemStack getStack() { + public ItemStack getStack() + { return this.stack; } @@ -60,7 +62,8 @@ public class TurtleInspectItemEvent extends TurtleActionEvent { * @return This items's inspection data. */ @Nonnull - public Map getData() { + public Map getData() + { return this.data; } @@ -69,7 +72,8 @@ public class TurtleInspectItemEvent extends TurtleActionEvent { * * @return If this is run on the main thread. */ - public boolean onMainThread() { + public boolean onMainThread() + { return this.mainThread; } @@ -78,8 +82,9 @@ public class TurtleInspectItemEvent extends TurtleActionEvent { * * @param newData The data to add. Note all values should be convertible to Lua (see {@link MethodResult#of(Object)}). */ - public void addData(@Nonnull Map newData) { - Objects.requireNonNull(newData, "newData cannot be null"); - this.data.putAll(newData); + public void addData( @Nonnull Map newData ) + { + Objects.requireNonNull( newData, "newData cannot be null" ); + this.data.putAll( newData ); } } diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleInventoryEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleInventoryEvent.java index 5ce7c83dd..61ff87594 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleInventoryEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleInventoryEvent.java @@ -6,28 +6,28 @@ package dan200.computercraft.api.turtle.event; -import java.util.Objects; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - 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; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; + /** * Fired when a turtle attempts to interact with an inventory. */ -public abstract class TurtleInventoryEvent extends TurtleBlockEvent { +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 Inventory 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; } @@ -37,7 +37,8 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent { * @return The inventory being interacted with, {@code null} if the item will be dropped to/sucked from the world. */ @Nullable - public Inventory getItemHandler() { + public Inventory getItemHandler() + { return this.handler; } @@ -46,9 +47,11 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent { * * @see TurtleAction#SUCK */ - 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); + 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 ); } } @@ -57,14 +60,16 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent { * * @see TurtleAction#DROP */ - 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 Inventory 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; } @@ -74,7 +79,8 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent { * @return The item stack which will be dropped. This should not be modified. */ @Nonnull - public ItemStack getStack() { + public ItemStack getStack() + { return this.stack; } } diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtlePlayerEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtlePlayerEvent.java index a48bf353a..54d79753c 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtlePlayerEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtlePlayerEvent.java @@ -6,25 +6,26 @@ 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 javax.annotation.Nonnull; +import java.util.Objects; + /** * 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; } @@ -36,7 +37,8 @@ public abstract class TurtlePlayerEvent extends TurtleActionEvent { * @return A {@link FakePlayer} representing this turtle. */ @Nonnull - public FakePlayer getPlayer() { + public FakePlayer getPlayer() + { return this.player; } } diff --git a/src/main/java/dan200/computercraft/api/turtle/event/TurtleRefuelEvent.java b/src/main/java/dan200/computercraft/api/turtle/event/TurtleRefuelEvent.java index ca0bdc7be..97c7e3a32 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/TurtleRefuelEvent.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/TurtleRefuelEvent.java @@ -6,14 +6,12 @@ package dan200.computercraft.api.turtle.event; -import java.util.Objects; +import dan200.computercraft.api.turtle.ITurtleAccess; +import net.minecraft.item.ItemStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; - -import dan200.computercraft.api.turtle.ITurtleAccess; - -import net.minecraft.item.ItemStack; +import java.util.Objects; /** * Fired when a turtle attempts to refuel from an item. @@ -21,14 +19,16 @@ import net.minecraft.item.ItemStack; * 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 { +public class TurtleRefuelEvent extends TurtleActionEvent +{ private final ItemStack stack; private Handler handler; - public TurtleRefuelEvent(@Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack) { - super(turtle, TurtleAction.REFUEL); + public TurtleRefuelEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack ) + { + super( turtle, TurtleAction.REFUEL ); - Objects.requireNonNull(turtle, "turtle cannot be null"); + Objects.requireNonNull( turtle, "turtle cannot be null" ); this.stack = stack; } @@ -39,7 +39,8 @@ public class TurtleRefuelEvent extends TurtleActionEvent { * * @return The stack to refuel from. */ - public ItemStack getStack() { + public ItemStack getStack() + { return this.stack; } @@ -50,7 +51,8 @@ public class TurtleRefuelEvent extends TurtleActionEvent { * @see #setHandler(Handler) */ @Nullable - public Handler getHandler() { + public Handler getHandler() + { return this.handler; } @@ -62,7 +64,8 @@ public class TurtleRefuelEvent extends TurtleActionEvent { * @param handler The new refuel handler. * @see #getHandler() */ - public void setHandler(@Nullable Handler handler) { + public void setHandler( @Nullable Handler handler ) + { this.handler = handler; } @@ -70,16 +73,17 @@ public class TurtleRefuelEvent extends TurtleActionEvent { * Handles refuelling a turtle from a specific item. */ @FunctionalInterface - public interface Handler { + 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. + * @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); + int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, int slot, int limit ); } } diff --git a/src/main/java/dan200/computercraft/client/ClientRegistry.java b/src/main/java/dan200/computercraft/client/ClientRegistry.java index ad02b7ae5..b1dd6e568 100644 --- a/src/main/java/dan200/computercraft/client/ClientRegistry.java +++ b/src/main/java/dan200/computercraft/client/ClientRegistry.java @@ -6,9 +6,6 @@ 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; @@ -16,7 +13,8 @@ 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.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; +import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.ModelLoader; @@ -27,17 +25,18 @@ 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; +import java.util.HashSet; +import java.util.function.Consumer; /** * Registers textures and models for items. */ -@SuppressWarnings ({ +@SuppressWarnings( { "MethodCallSideOnly", "LocalVariableDeclarationSideOnly" -}) -public final class ClientRegistry { +} ) +public final class ClientRegistry +{ private static final String[] EXTRA_MODELS = new String[] { "turtle_modem_normal_off_left", "turtle_modem_normal_on_left", @@ -56,7 +55,7 @@ public final class ClientRegistry { "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 @@ -65,59 +64,66 @@ public final class ClientRegistry { "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)); + 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 out) { - for (String model : EXTRA_MODELS) { - out.accept(new ModelIdentifier(new Identifier(ComputerCraft.MOD_ID, model), "inventory")); + @SuppressWarnings( "NewExpressionSideOnly" ) + public static void onModelBakeEvent( ResourceManager manager, Consumer 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); + 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 ) -> 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 + ColorProviderRegistry.ITEM.register( ( stack, layer ) -> { + switch( layer ) { - int light = ItemPocketComputer.getLightState(stack); - return light == -1 ? Colour.BLACK.getHex() : light; + 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); + }, 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); + 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); + 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 ); } } diff --git a/src/main/java/dan200/computercraft/client/ClientTableFormatter.java b/src/main/java/dan200/computercraft/client/ClientTableFormatter.java index d3cd9b7bf..a7ccd63d1 100644 --- a/src/main/java/dan200/computercraft/client/ClientTableFormatter.java +++ b/src/main/java/dan200/computercraft/client/ClientTableFormatter.java @@ -6,64 +6,70 @@ 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 org.apache.commons.lang3.StringUtils; - 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; +import org.apache.commons.lang3.StringUtils; -@SuppressWarnings ({ +import javax.annotation.Nullable; + +@SuppressWarnings( { "MethodCallSideOnly", "LocalVariableDeclarationSideOnly" -}) -public class ClientTableFormatter implements TableFormatter { +} ) +public class ClientTableFormatter implements TableFormatter +{ public static final ClientTableFormatter INSTANCE = new ClientTableFormatter(); private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap(); @Override @Nullable - public Text getPadding(Text component, int width) { - int extraWidth = width - this.getWidth(component); - if (extraWidth <= 0) { + public Text getPadding( Text component, int width ) + { + int extraWidth = width - this.getWidth( component ); + if( extraWidth <= 0 ) + { return null; } TextRenderer renderer = renderer(); - float spaceWidth = renderer.getWidth(" "); - 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), Formatting.GRAY); + return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), Formatting.GRAY ); } - private static TextRenderer renderer() { + private static TextRenderer renderer() + { return MinecraftClient.getInstance().textRenderer; } @Override - public int getColumnPadding() { + public int getColumnPadding() + { return 3; } @Override - public int getWidth(Text component) { - return renderer().getWidth(component); + public int getWidth( Text component ) + { + return renderer().getWidth( component ); } @Override - public void writeLine(int id, Text component) { + public void writeLine( int id, Text component ) + { MinecraftClient mc = MinecraftClient.getInstance(); ChatHud chat = mc.inGameHud.getChatHud(); @@ -71,20 +77,22 @@ public class ClientTableFormatter implements TableFormatter { // int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() ); // List list = RenderComponentsUtil.func_238505_a_( component, maxWidth, mc.fontRenderer ); // if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id ); - ((ChatHudAccess)chat).callAddMessage(component, id); + ((ChatHudAccess) chat).callAddMessage( component, id ); } @Override - public int display(TableBuilder table) { + 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++) { - ((ChatHudAccess)chat).callRemoveMessage(i + table.getId()); + for( int i = height; i < lastHeight; i++ ) + { + ((ChatHudAccess) chat).callRemoveMessage( i + table.getId() ); } return height; } diff --git a/src/main/java/dan200/computercraft/client/FrameInfo.java b/src/main/java/dan200/computercraft/client/FrameInfo.java index 9380b6e0b..7afc250e9 100644 --- a/src/main/java/dan200/computercraft/client/FrameInfo.java +++ b/src/main/java/dan200/computercraft/client/FrameInfo.java @@ -8,38 +8,46 @@ package dan200.computercraft.client; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -public final class FrameInfo { +public final class FrameInfo +{ private static int tick; private static long renderFrame; - static { + static + { } - private FrameInfo() { + private FrameInfo() + { } - public static void init() { - ClientTickEvents.START_CLIENT_TICK.register(m -> { + public static void init() + { + ClientTickEvents.START_CLIENT_TICK.register( m -> { tick++; - }); + } ); } - public static boolean getGlobalCursorBlink() { + public static boolean getGlobalCursorBlink() + { return (tick / 8) % 2 == 0; } - public static long getRenderFrame() { + public static long getRenderFrame() + { return renderFrame; } // TODO Call this in a callback - public static void onTick() { + public static void onTick() + { tick++; } // TODO Call this in a callback - public static void onRenderFrame() { + public static void onRenderFrame() + { renderFrame++; } } diff --git a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java index 59d855fca..48a8b6aed 100644 --- a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java +++ b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java @@ -6,159 +6,175 @@ package dan200.computercraft.client.gui; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.client.FrameInfo; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; -import org.lwjgl.opengl.GL11; - import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.RenderPhase; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexFormat; -import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.render.*; import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.util.Identifier; import net.minecraft.util.math.Matrix4f; +import org.lwjgl.opengl.GL11; -public final class FixedWidthFontRenderer { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public final class FixedWidthFontRenderer +{ public static final int FONT_HEIGHT = 9; public static final int FONT_WIDTH = 6; public static final float WIDTH = 256.0f; public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; private static final Matrix4f IDENTITY = AffineTransformation.identity() - .getMatrix(); - private static final Identifier FONT = new Identifier("computercraft", "textures/gui/term_font.png"); + .getMatrix(); + private static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" ); public static final RenderLayer TYPE = Type.MAIN; - private FixedWidthFontRenderer() { + private FixedWidthFontRenderer() + { } - public static void drawString(float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, - @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize) { + public static void drawString( float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, + @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize ) + { bindFont(); VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - drawString(IDENTITY, - ((VertexConsumerProvider) renderer).getBuffer(TYPE), - x, - y, - text, - textColour, - backgroundColour, - palette, - greyscale, - leftMarginSize, - rightMarginSize); + .getBufferBuilders() + .getEntityVertexConsumers(); + drawString( IDENTITY, + ((VertexConsumerProvider) renderer).getBuffer( TYPE ), + x, + y, + text, + textColour, + backgroundColour, + palette, + greyscale, + leftMarginSize, + rightMarginSize ); renderer.draw(); } - private static void bindFont() { + private static void bindFont() + { MinecraftClient.getInstance() - .getTextureManager() - .bindTexture(FONT); - RenderSystem.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP); + .getTextureManager() + .bindTexture( FONT ); + RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); } - public static void drawString(@Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, @Nonnull TextBuffer text, - @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, - float leftMarginSize, float rightMarginSize) { - if (backgroundColour != null) { - drawBackground(transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT); + public static void drawString( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, @Nonnull TextBuffer text, + @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, + float leftMarginSize, float rightMarginSize ) + { + if( backgroundColour != null ) + { + drawBackground( transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT ); } - for (int i = 0; i < text.length(); i++) { - double[] colour = palette.getColour(getColour(textColour.charAt(i), Colour.BLACK)); + for( int i = 0; i < text.length(); i++ ) + { + double[] colour = palette.getColour( getColour( textColour.charAt( i ), Colour.BLACK ) ); float r, g, b; - if (greyscale) { - r = g = b = toGreyscale(colour); - } else { + if( greyscale ) + { + r = g = b = toGreyscale( colour ); + } + else + { r = (float) colour[0]; g = (float) colour[1]; b = (float) colour[2]; } // Draw char - int index = text.charAt(i); - if (index > 255) { + int index = text.charAt( i ); + if( index > 255 ) + { index = '?'; } - drawChar(transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b); + drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b ); } } - private static void drawBackground(@Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, - @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, float leftMarginSize, - float rightMarginSize, float height) { - if (leftMarginSize > 0) { - drawQuad(transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt(0)); + private static void drawBackground( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, + @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, float leftMarginSize, + float rightMarginSize, float height ) + { + if( leftMarginSize > 0 ) + { + drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) ); } - if (rightMarginSize > 0) { - drawQuad(transform, - renderer, - x + backgroundColour.length() * FONT_WIDTH, - y, - rightMarginSize, - height, - palette, - greyscale, - backgroundColour.charAt(backgroundColour.length() - 1)); + if( rightMarginSize > 0 ) + { + drawQuad( transform, + renderer, + x + backgroundColour.length() * FONT_WIDTH, + y, + rightMarginSize, + height, + palette, + greyscale, + backgroundColour.charAt( backgroundColour.length() - 1 ) ); } // Batch together runs of identical background cells. int blockStart = 0; char blockColour = '\0'; - for (int i = 0; i < backgroundColour.length(); i++) { - char colourIndex = backgroundColour.charAt(i); - if (colourIndex == blockColour) { + for( int i = 0; i < backgroundColour.length(); i++ ) + { + char colourIndex = backgroundColour.charAt( i ); + if( colourIndex == blockColour ) + { continue; } - if (blockColour != '\0') { - drawQuad(transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour); + if( blockColour != '\0' ) + { + drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour ); } blockColour = colourIndex; blockStart = i; } - if (blockColour != '\0') { - drawQuad(transform, - renderer, - x + blockStart * FONT_WIDTH, - y, - FONT_WIDTH * (backgroundColour.length() - blockStart), - height, - palette, - greyscale, - blockColour); + if( blockColour != '\0' ) + { + drawQuad( transform, + renderer, + x + blockStart * FONT_WIDTH, + y, + FONT_WIDTH * (backgroundColour.length() - blockStart), + height, + palette, + greyscale, + blockColour ); } } - public static int getColour(char c, Colour def) { - return 15 - Terminal.getColour(c, def); + public static int getColour( char c, Colour def ) + { + return 15 - Terminal.getColour( c, def ); } - public static float toGreyscale(double[] rgb) { + public static float toGreyscale( double[] rgb ) + { return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3); } - private static void drawChar(Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b) { + private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b ) + { // Short circuit to avoid the common case - the texture should be blank here after all. - if (index == '\0' || index == ' ') { + if( index == '\0' || index == ' ' ) + { return; } @@ -168,217 +184,238 @@ public final class FixedWidthFontRenderer { int xStart = 1 + column * (FONT_WIDTH + 2); int yStart = 1 + row * (FONT_HEIGHT + 2); - buffer.vertex(transform, x, y, 0f) - .color(r, g, b, 1.0f) - .texture(xStart / WIDTH, yStart / WIDTH) - .next(); - buffer.vertex(transform, x, y + FONT_HEIGHT, 0f) - .color(r, g, b, 1.0f) - .texture(xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH) - .next(); - buffer.vertex(transform, x + FONT_WIDTH, y, 0f) - .color(r, g, b, 1.0f) - .texture((xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH) - .next(); - buffer.vertex(transform, x + FONT_WIDTH, y, 0f) - .color(r, g, b, 1.0f) - .texture((xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH) - .next(); - buffer.vertex(transform, x, y + FONT_HEIGHT, 0f) - .color(r, g, b, 1.0f) - .texture(xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH) - .next(); - buffer.vertex(transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f) - .color(r, g, b, 1.0f) - .texture((xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH) - .next(); + buffer.vertex( transform, x, y, 0f ) + .color( r, g, b, 1.0f ) + .texture( xStart / WIDTH, yStart / WIDTH ) + .next(); + buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ) + .color( r, g, b, 1.0f ) + .texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ) + .next(); + buffer.vertex( transform, x + FONT_WIDTH, y, 0f ) + .color( r, g, b, 1.0f ) + .texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ) + .next(); + buffer.vertex( transform, x + FONT_WIDTH, y, 0f ) + .color( r, g, b, 1.0f ) + .texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ) + .next(); + buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ) + .color( r, g, b, 1.0f ) + .texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ) + .next(); + buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ) + .color( r, g, b, 1.0f ) + .texture( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ) + .next(); } - private static void drawQuad(Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, - boolean greyscale, char colourIndex) { - double[] colour = palette.getColour(getColour(colourIndex, Colour.BLACK)); + private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, + boolean greyscale, char colourIndex ) + { + double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) ); float r, g, b; - if (greyscale) { - r = g = b = toGreyscale(colour); - } else { + if( greyscale ) + { + r = g = b = toGreyscale( colour ); + } + else + { r = (float) colour[0]; g = (float) colour[1]; b = (float) colour[2]; } - drawQuad(transform, buffer, x, y, width, height, r, g, b); + drawQuad( transform, buffer, x, y, width, height, r, g, b ); } - private static void drawQuad(Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b) { - buffer.vertex(transform, x, y, 0) - .color(r, g, b, 1.0f) - .texture(BACKGROUND_START, BACKGROUND_START) - .next(); - buffer.vertex(transform, x, y + height, 0) - .color(r, g, b, 1.0f) - .texture(BACKGROUND_START, BACKGROUND_END) - .next(); - buffer.vertex(transform, x + width, y, 0) - .color(r, g, b, 1.0f) - .texture(BACKGROUND_END, BACKGROUND_START) - .next(); - buffer.vertex(transform, x + width, y, 0) - .color(r, g, b, 1.0f) - .texture(BACKGROUND_END, BACKGROUND_START) - .next(); - buffer.vertex(transform, x, y + height, 0) - .color(r, g, b, 1.0f) - .texture(BACKGROUND_START, BACKGROUND_END) - .next(); - buffer.vertex(transform, x + width, y + height, 0) - .color(r, g, b, 1.0f) - .texture(BACKGROUND_END, BACKGROUND_END) - .next(); + private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b ) + { + buffer.vertex( transform, x, y, 0 ) + .color( r, g, b, 1.0f ) + .texture( BACKGROUND_START, BACKGROUND_START ) + .next(); + buffer.vertex( transform, x, y + height, 0 ) + .color( r, g, b, 1.0f ) + .texture( BACKGROUND_START, BACKGROUND_END ) + .next(); + buffer.vertex( transform, x + width, y, 0 ) + .color( r, g, b, 1.0f ) + .texture( BACKGROUND_END, BACKGROUND_START ) + .next(); + buffer.vertex( transform, x + width, y, 0 ) + .color( r, g, b, 1.0f ) + .texture( BACKGROUND_END, BACKGROUND_START ) + .next(); + buffer.vertex( transform, x, y + height, 0 ) + .color( r, g, b, 1.0f ) + .texture( BACKGROUND_START, BACKGROUND_END ) + .next(); + buffer.vertex( transform, x + width, y + height, 0 ) + .color( r, g, b, 1.0f ) + .texture( BACKGROUND_END, BACKGROUND_END ) + .next(); } - public static void drawTerminalWithoutCursor(@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, - @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, - float leftMarginSize, float rightMarginSize) { + public static void drawTerminalWithoutCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, + @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, + float leftMarginSize, float rightMarginSize ) + { Palette palette = terminal.getPalette(); int height = terminal.getHeight(); // Top and bottom margins - drawBackground(transform, - buffer, - x, - y - topMarginSize, - terminal.getBackgroundColourLine(0), - palette, - greyscale, - leftMarginSize, - rightMarginSize, - topMarginSize); + drawBackground( transform, + buffer, + x, + y - topMarginSize, + terminal.getBackgroundColourLine( 0 ), + palette, + greyscale, + leftMarginSize, + rightMarginSize, + topMarginSize ); - drawBackground(transform, - buffer, - x, - y + height * FONT_HEIGHT, - terminal.getBackgroundColourLine(height - 1), - palette, - greyscale, - leftMarginSize, - rightMarginSize, - bottomMarginSize); + drawBackground( transform, + buffer, + x, + y + height * FONT_HEIGHT, + terminal.getBackgroundColourLine( height - 1 ), + palette, + greyscale, + leftMarginSize, + rightMarginSize, + bottomMarginSize ); // The main text - for (int i = 0; i < height; i++) { - drawString(transform, - buffer, - x, - y + FixedWidthFontRenderer.FONT_HEIGHT * i, - terminal.getLine(i), - terminal.getTextColourLine(i), - terminal.getBackgroundColourLine(i), - palette, - greyscale, - leftMarginSize, - rightMarginSize); + for( int i = 0; i < height; i++ ) + { + drawString( transform, + buffer, + x, + y + FixedWidthFontRenderer.FONT_HEIGHT * i, + terminal.getLine( i ), + terminal.getTextColourLine( i ), + terminal.getBackgroundColourLine( i ), + palette, + greyscale, + leftMarginSize, + rightMarginSize ); } } - public static void drawCursor(@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal, - boolean greyscale) { + public static void drawCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal, + boolean greyscale ) + { Palette palette = terminal.getPalette(); int width = terminal.getWidth(); int height = terminal.getHeight(); int cursorX = terminal.getCursorX(); int cursorY = terminal.getCursorY(); - if (terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height && FrameInfo.getGlobalCursorBlink()) { - double[] colour = palette.getColour(15 - terminal.getTextColour()); + if( terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height && FrameInfo.getGlobalCursorBlink() ) + { + double[] colour = palette.getColour( 15 - terminal.getTextColour() ); float r, g, b; - if (greyscale) { - r = g = b = toGreyscale(colour); - } else { + if( greyscale ) + { + r = g = b = toGreyscale( colour ); + } + else + { r = (float) colour[0]; g = (float) colour[1]; b = (float) colour[2]; } - drawChar(transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b); + drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b ); } } - public static void drawTerminal(@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal, - boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize) { - drawTerminalWithoutCursor(transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize); - drawCursor(transform, buffer, x, y, terminal, greyscale); + public static void drawTerminal( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal, + boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize ) + { + drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); + drawCursor( transform, buffer, x, y, terminal, greyscale ); } - public static void drawTerminal(@Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, - float bottomMarginSize, float leftMarginSize, float rightMarginSize) { + public static void drawTerminal( @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, + float bottomMarginSize, float leftMarginSize, float rightMarginSize ) + { bindFont(); VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - VertexConsumer buffer = renderer.getBuffer(TYPE); - drawTerminal(transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize); - renderer.draw(TYPE); + .getBufferBuilders() + .getEntityVertexConsumers(); + VertexConsumer buffer = renderer.getBuffer( TYPE ); + drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); + renderer.draw( TYPE ); } - public static void drawTerminal(float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, - float leftMarginSize, float rightMarginSize) { - drawTerminal(IDENTITY, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize); + public static void drawTerminal( float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, + float leftMarginSize, float rightMarginSize ) + { + drawTerminal( IDENTITY, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); } - public static void drawEmptyTerminal(float x, float y, float width, float height) { - drawEmptyTerminal(IDENTITY, x, y, width, height); + public static void drawEmptyTerminal( float x, float y, float width, float height ) + { + drawEmptyTerminal( IDENTITY, x, y, width, height ); } - public static void drawEmptyTerminal(@Nonnull Matrix4f transform, float x, float y, float width, float height) { + public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height ) + { bindFont(); VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - drawEmptyTerminal(transform, renderer, x, y, width, height); + .getBufferBuilders() + .getEntityVertexConsumers(); + drawEmptyTerminal( transform, renderer, x, y, width, height ); renderer.draw(); } - public static void drawEmptyTerminal(@Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, - float height) { + public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, + float height ) + { Colour colour = Colour.BLACK; - drawQuad(transform, renderer.getBuffer(TYPE), x, y, width, height, colour.getR(), colour.getG(), colour.getB()); + drawQuad( transform, renderer.getBuffer( TYPE ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); } - public static void drawBlocker(@Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, float height) { + public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, float height ) + { Colour colour = Colour.BLACK; - drawQuad(transform, renderer.getBuffer(Type.BLOCKER), x, y, width, height, colour.getR(), colour.getG(), colour.getB()); + drawQuad( transform, renderer.getBuffer( Type.BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); } - private static final class Type extends RenderPhase { + private static final class Type extends RenderPhase + { private static final int GL_MODE = GL11.GL_TRIANGLES; private static final VertexFormat FORMAT = VertexFormats.POSITION_COLOR_TEXTURE; - static final RenderLayer MAIN = RenderLayer.of("terminal_font", FORMAT, GL_MODE, 1024, false, false, // useDelegate, needsSorting - RenderLayer.MultiPhaseParameters.builder() - .texture(new RenderPhase.Texture(FONT, - false, - false)) // blur, minimap - .alpha(ONE_TENTH_ALPHA) - .lightmap(DISABLE_LIGHTMAP) - .writeMaskState(COLOR_MASK) - .build(false)); + static final RenderLayer MAIN = RenderLayer.of( "terminal_font", FORMAT, GL_MODE, 1024, false, false, // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( new RenderPhase.Texture( FONT, + false, + false ) ) // blur, minimap + .alpha( ONE_TENTH_ALPHA ) + .lightmap( DISABLE_LIGHTMAP ) + .writeMaskState( COLOR_MASK ) + .build( false ) ); - static final RenderLayer BLOCKER = RenderLayer.of("terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting - RenderLayer.MultiPhaseParameters.builder() - .texture(new RenderPhase.Texture(FONT, - false, - false)) // blur, minimap - .alpha(ONE_TENTH_ALPHA) - .writeMaskState(DEPTH_MASK) - .lightmap(DISABLE_LIGHTMAP) - .build(false)); + static final RenderLayer BLOCKER = RenderLayer.of( "terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( new RenderPhase.Texture( FONT, + false, + false ) ) // blur, minimap + .alpha( ONE_TENTH_ALPHA ) + .writeMaskState( DEPTH_MASK ) + .lightmap( DISABLE_LIGHTMAP ) + .build( false ) ); - private Type(String name, Runnable setup, Runnable destroy) { - super(name, setup, destroy); + private Type( String name, Runnable setup, Runnable destroy ) + { + super( name, setup, destroy ); } } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java index 64c8c5701..0a8268615 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -6,11 +6,6 @@ package dan200.computercraft.client.gui; -import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; -import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; - -import javax.annotation.Nonnull; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.widgets.WidgetTerminal; @@ -22,14 +17,19 @@ import dan200.computercraft.shared.computer.inventory.ContainerComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import org.lwjgl.glfw.GLFW; - import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; -public final class GuiComputer extends HandledScreen { +import javax.annotation.Nonnull; + +import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; +import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; + +public final class GuiComputer extends HandledScreen +{ private final ComputerFamily family; private final ClientComputer computer; private final int termWidth; @@ -38,8 +38,9 @@ public final class GuiComputer extends HandledS private WidgetTerminal terminal; private WidgetWrapper terminalWrapper; - private GuiComputer(T container, PlayerInventory player, Text title, int termWidth, int termHeight) { - super(container, player, title); + private GuiComputer( T container, PlayerInventory player, Text title, int termWidth, int termHeight ) + { + super( container, player, title ); this.family = container.getFamily(); this.computer = (ClientComputer) container.getComputer(); this.termWidth = termWidth; @@ -47,22 +48,26 @@ public final class GuiComputer extends HandledS this.terminal = null; } - public static GuiComputer create(ContainerComputer container, PlayerInventory inventory, Text component) { - return new GuiComputer<>(container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight); + public static GuiComputer create( ContainerComputer container, PlayerInventory inventory, Text component ) + { + return new GuiComputer<>( container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight ); } - public static GuiComputer createPocket(ContainerPocketComputer container, PlayerInventory inventory, Text component) { - return new GuiComputer<>(container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight); + public static GuiComputer createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component ) + { + return new GuiComputer<>( container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ); } - public static GuiComputer createView(ContainerViewComputer container, PlayerInventory inventory, Text component) { - return new GuiComputer<>(container, inventory, component, container.getWidth(), container.getHeight()); + public static GuiComputer createView( ContainerViewComputer container, PlayerInventory inventory, Text component ) + { + return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() ); } @Override - protected void init() { - this.client.keyboard.setRepeatEvents(true); + protected void init() + { + this.client.keyboard.setRepeatEvents( true ); int termPxWidth = this.termWidth * FixedWidthFontRenderer.FONT_WIDTH; int termPxHeight = this.termHeight * FixedWidthFontRenderer.FONT_HEIGHT; @@ -72,67 +77,76 @@ public final class GuiComputer extends HandledS super.init(); - this.terminal = new WidgetTerminal(this.client, () -> this.computer, this.termWidth, this.termHeight, MARGIN, MARGIN, MARGIN, MARGIN); - this.terminalWrapper = new WidgetWrapper(this.terminal, MARGIN + BORDER + this.x, MARGIN + BORDER + this.y, termPxWidth, termPxHeight); + this.terminal = new WidgetTerminal( this.client, () -> this.computer, this.termWidth, this.termHeight, MARGIN, MARGIN, MARGIN, MARGIN ); + this.terminalWrapper = new WidgetWrapper( this.terminal, MARGIN + BORDER + this.x, MARGIN + BORDER + this.y, termPxWidth, termPxHeight ); - this.children.add(this.terminalWrapper); - this.setFocused(this.terminalWrapper); + this.children.add( this.terminalWrapper ); + this.setFocused( this.terminalWrapper ); } @Override - public void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks) { - super.render(stack, mouseX, mouseY, partialTicks); - this.drawMouseoverTooltip(stack, mouseX, mouseY); + public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) + { + super.render( stack, mouseX, mouseY, partialTicks ); + this.drawMouseoverTooltip( stack, mouseX, mouseY ); } @Override - protected void drawForeground(@Nonnull MatrixStack transform, int mouseX, int mouseY) { + protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) + { // Skip rendering labels. } @Override - public void drawBackground(@Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY) { + public void drawBackground( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY ) + { // Draw terminal - this.terminal.draw(this.terminalWrapper.getX(), this.terminalWrapper.getY()); + this.terminal.draw( this.terminalWrapper.getX(), this.terminalWrapper.getY() ); // Draw a border around the terminal - RenderSystem.color4f(1, 1, 1, 1); + RenderSystem.color4f( 1, 1, 1, 1 ); this.client.getTextureManager() - .bindTexture(ComputerBorderRenderer.getTexture(this.family)); - ComputerBorderRenderer.render(this.terminalWrapper.getX() - MARGIN, this.terminalWrapper.getY() - MARGIN, - this.getZOffset(), this.terminalWrapper.getWidth() + MARGIN * 2, this.terminalWrapper.getHeight() + MARGIN * 2); + .bindTexture( ComputerBorderRenderer.getTexture( this.family ) ); + ComputerBorderRenderer.render( this.terminalWrapper.getX() - MARGIN, this.terminalWrapper.getY() - MARGIN, + this.getZOffset(), this.terminalWrapper.getWidth() + MARGIN * 2, this.terminalWrapper.getHeight() + MARGIN * 2 ); } @Override - public boolean mouseDragged(double x, double y, int button, double deltaX, double deltaY) { - return (this.getFocused() != null && this.getFocused().mouseDragged(x, y, button, deltaX, deltaY)) || super.mouseDragged(x, y, button, deltaX, deltaY); + public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) + { + return (this.getFocused() != null && this.getFocused().mouseDragged( x, y, button, deltaX, deltaY )) || super.mouseDragged( x, y, button, deltaX, deltaY ); } - @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - return (this.getFocused() != null && this.getFocused().mouseReleased(mouseX, mouseY, button)) || super.mouseReleased(x, y, button); - } + @Override + public boolean mouseReleased( double mouseX, double mouseY, int button ) + { + return (this.getFocused() != null && this.getFocused().mouseReleased( mouseX, mouseY, button )) || super.mouseReleased( x, y, button ); + } @Override - public boolean keyPressed(int key, int scancode, int modifiers) { + public boolean keyPressed( int key, int scancode, int modifiers ) + { // Forward the tab key to the terminal, rather than moving between controls. - if (key == GLFW.GLFW_KEY_TAB && this.getFocused() != null && this.getFocused() == this.terminalWrapper) { - return this.getFocused().keyPressed(key, scancode, modifiers); + if( key == GLFW.GLFW_KEY_TAB && this.getFocused() != null && this.getFocused() == this.terminalWrapper ) + { + return this.getFocused().keyPressed( key, scancode, modifiers ); } - return super.keyPressed(key, scancode, modifiers); + return super.keyPressed( key, scancode, modifiers ); } @Override - public void removed() { + public void removed() + { super.removed(); - this.children.remove(this.terminal); + this.children.remove( this.terminal ); this.terminal = null; - this.client.keyboard.setRepeatEvents(false); + this.client.keyboard.setRepeatEvents( false ); } @Override - public void tick() { + public void tick() + { super.tick(); this.terminal.update(); } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java index 676cd8d16..b098d37c5 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java @@ -6,36 +6,39 @@ package dan200.computercraft.client.gui; -import javax.annotation.Nonnull; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; - import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -public class GuiDiskDrive extends HandledScreen { - private static final Identifier BACKGROUND = new Identifier("computercraft", "textures/gui/disk_drive.png"); +import javax.annotation.Nonnull; - public GuiDiskDrive(ContainerDiskDrive container, PlayerInventory player, Text title) { - super(container, player, title); +public class GuiDiskDrive extends HandledScreen +{ + private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/disk_drive.png" ); + + public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory player, Text title ) + { + super( container, player, title ); } @Override - public void render(@Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(transform); - super.render(transform, mouseX, mouseY, partialTicks); - this.drawMouseoverTooltip(transform, mouseX, mouseY); + public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks ) + { + this.renderBackground( transform ); + super.render( transform, mouseX, mouseY, partialTicks ); + this.drawMouseoverTooltip( transform, mouseX, mouseY ); } @Override - protected void drawBackground(@Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY) { - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) + { + RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F ); this.client.getTextureManager() - .bindTexture(BACKGROUND); - this.drawTexture(transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight); + .bindTexture( BACKGROUND ); + this.drawTexture( transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight ); } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java index 0e2f2f4bc..48988356a 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java @@ -6,22 +6,23 @@ package dan200.computercraft.client.gui; -import javax.annotation.Nonnull; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; - import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -public class GuiPrinter extends HandledScreen { - private static final Identifier BACKGROUND = new Identifier("computercraft", "textures/gui/printer.png"); +import javax.annotation.Nonnull; - public GuiPrinter(ContainerPrinter container, PlayerInventory player, Text title) { - super(container, player, title); +public class GuiPrinter extends HandledScreen +{ + private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/printer.png" ); + + public GuiPrinter( ContainerPrinter container, PlayerInventory player, Text title ) + { + super( container, player, title ); } /*@Override @@ -33,21 +34,24 @@ public class GuiPrinter extends HandledScreen { }*/ @Override - public void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(stack); - super.render(stack, mouseX, mouseY, partialTicks); - this.drawMouseoverTooltip(stack, mouseX, mouseY); + public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) + { + this.renderBackground( stack ); + super.render( stack, mouseX, mouseY, partialTicks ); + this.drawMouseoverTooltip( stack, mouseX, mouseY ); } @Override - protected void drawBackground(@Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY) { - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) + { + RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F ); this.client.getTextureManager() - .bindTexture(BACKGROUND); - this.drawTexture(transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight); + .bindTexture( BACKGROUND ); + this.drawTexture( transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight ); - if (this.getScreenHandler().isPrinting()) { - this.drawTexture(transform, this.x + 34, this.y + 21, 176, 0, 25, 45); + if( this.getScreenHandler().isPrinting() ) + { + this.drawTexture( transform, this.x + 34, this.y + 21, 176, 0, 25, 45 ); } } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java index 49bacd902..c944aaed4 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java @@ -6,20 +6,10 @@ package dan200.computercraft.client.gui; -import static dan200.computercraft.client.render.PrintoutRenderer.X_TEXT_MARGIN; -import static dan200.computercraft.client.render.PrintoutRenderer.Y_SIZE; -import static dan200.computercraft.client.render.PrintoutRenderer.Y_TEXT_MARGIN; -import static dan200.computercraft.client.render.PrintoutRenderer.drawBorder; -import static dan200.computercraft.client.render.PrintoutRenderer.drawText; - -import javax.annotation.Nonnull; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.common.ContainerHeldItem; import dan200.computercraft.shared.media.items.ItemPrintout; -import org.lwjgl.glfw.GLFW; - import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.render.VertexConsumerProvider; @@ -27,53 +17,68 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.text.Text; import net.minecraft.util.math.Matrix4f; +import org.lwjgl.glfw.GLFW; -public class GuiPrintout extends HandledScreen { +import javax.annotation.Nonnull; + +import static dan200.computercraft.client.render.PrintoutRenderer.*; + +public class GuiPrintout extends HandledScreen +{ private final boolean m_book; private final int m_pages; private final TextBuffer[] m_text; private final TextBuffer[] m_colours; private int m_page; - public GuiPrintout(ContainerHeldItem container, PlayerInventory player, Text title) { - super(container, player, title); + public GuiPrintout( ContainerHeldItem container, PlayerInventory player, Text title ) + { + super( container, player, title ); this.backgroundHeight = Y_SIZE; - String[] text = ItemPrintout.getText(container.getStack()); + String[] text = ItemPrintout.getText( container.getStack() ); this.m_text = new TextBuffer[text.length]; - for (int i = 0; i < this.m_text.length; i++) { - this.m_text[i] = new TextBuffer(text[i]); + for( int i = 0; i < this.m_text.length; i++ ) + { + this.m_text[i] = new TextBuffer( text[i] ); } - String[] colours = ItemPrintout.getColours(container.getStack()); + String[] colours = ItemPrintout.getColours( container.getStack() ); this.m_colours = new TextBuffer[colours.length]; - for (int i = 0; i < this.m_colours.length; i++) { - this.m_colours[i] = new TextBuffer(colours[i]); + for( int i = 0; i < this.m_colours.length; i++ ) + { + this.m_colours[i] = new TextBuffer( colours[i] ); } this.m_page = 0; - this.m_pages = Math.max(this.m_text.length / ItemPrintout.LINES_PER_PAGE, 1); + this.m_pages = Math.max( this.m_text.length / ItemPrintout.LINES_PER_PAGE, 1 ); this.m_book = ((ItemPrintout) container.getStack() - .getItem()).getType() == ItemPrintout.Type.BOOK; + .getItem()).getType() == ItemPrintout.Type.BOOK; } @Override - public boolean mouseScrolled(double x, double y, double delta) { - if (super.mouseScrolled(x, y, delta)) { + public boolean mouseScrolled( double x, double y, double delta ) + { + if( super.mouseScrolled( x, y, delta ) ) + { return true; } - if (delta < 0) { + if( delta < 0 ) + { // Scroll up goes to the next page - if (this.m_page < this.m_pages - 1) { + if( this.m_page < this.m_pages - 1 ) + { this.m_page++; } return true; } - if (delta > 0) { + if( delta > 0 ) + { // Scroll down goes to the previous page - if (this.m_page > 0) { + if( this.m_page > 0 ) + { this.m_page--; } return true; @@ -83,51 +88,60 @@ public class GuiPrintout extends HandledScreen { } @Override - public void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks) { + public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) + { // We must take the background further back in order to not overlap with our printed pages. - this.setZOffset(this.getZOffset() - 1); - this.renderBackground(stack); - this.setZOffset(this.getZOffset() + 1); + this.setZOffset( this.getZOffset() - 1 ); + this.renderBackground( stack ); + this.setZOffset( this.getZOffset() + 1 ); - super.render(stack, mouseX, mouseY, partialTicks); + super.render( stack, mouseX, mouseY, partialTicks ); } @Override - protected void drawForeground(@Nonnull MatrixStack transform, int mouseX, int mouseY) { + protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) + { // Skip rendering labels. } @Override - protected void drawBackground(@Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY) { + protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) + { // Draw the printout - RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f); + RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f ); RenderSystem.enableDepthTest(); VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); + .getBufferBuilders() + .getEntityVertexConsumers(); Matrix4f matrix = transform.peek() - .getModel(); - drawBorder(matrix, renderer, this.x, this.y, this.getZOffset(), this.m_page, this.m_pages, this.m_book); - drawText(matrix, renderer, this.x + X_TEXT_MARGIN, this.y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * this.m_page, this.m_text, this.m_colours); + .getModel(); + drawBorder( matrix, renderer, this.x, this.y, this.getZOffset(), this.m_page, this.m_pages, this.m_book ); + drawText( matrix, renderer, this.x + X_TEXT_MARGIN, this.y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * this.m_page, this.m_text, this.m_colours ); renderer.draw(); } @Override - public boolean keyPressed(int key, int scancode, int modifiers) { - if (super.keyPressed(key, scancode, modifiers)) { + public boolean keyPressed( int key, int scancode, int modifiers ) + { + if( super.keyPressed( key, scancode, modifiers ) ) + { return true; } - if (key == GLFW.GLFW_KEY_RIGHT) { - if (this.m_page < this.m_pages - 1) { + if( key == GLFW.GLFW_KEY_RIGHT ) + { + if( this.m_page < this.m_pages - 1 ) + { this.m_page++; } return true; } - if (key == GLFW.GLFW_KEY_LEFT) { - if (this.m_page > 0) { + if( key == GLFW.GLFW_KEY_LEFT ) + { + if( this.m_page > 0 ) + { this.m_page--; } return true; diff --git a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java index 609c656ef..4a731ad2a 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java @@ -6,8 +6,6 @@ package dan200.computercraft.client.gui; -import javax.annotation.Nonnull; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.widgets.WidgetTerminal; @@ -15,25 +13,28 @@ import dan200.computercraft.client.gui.widgets.WidgetWrapper; import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; -import org.lwjgl.glfw.GLFW; - import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.lwjgl.glfw.GLFW; -public class GuiTurtle extends HandledScreen { - private static final Identifier BACKGROUND_NORMAL = new Identifier("computercraft", "textures/gui/turtle_normal.png"); - private static final Identifier BACKGROUND_ADVANCED = new Identifier("computercraft", "textures/gui/turtle_advanced.png"); +import javax.annotation.Nonnull; + +public class GuiTurtle extends HandledScreen +{ + private static final Identifier BACKGROUND_NORMAL = new Identifier( "computercraft", "textures/gui/turtle_normal.png" ); + private static final Identifier BACKGROUND_ADVANCED = new Identifier( "computercraft", "textures/gui/turtle_advanced.png" ); private final ComputerFamily m_family; private final ClientComputer m_computer; private ContainerTurtle m_container; private WidgetTerminal terminal; private WidgetWrapper terminalWrapper; - public GuiTurtle(ContainerTurtle container, PlayerInventory player, Text title) { - super(container, player, title); + public GuiTurtle( ContainerTurtle container, PlayerInventory player, Text title ) + { + super( container, player, title ); this.m_container = container; this.m_family = container.getFamily(); @@ -44,82 +45,92 @@ public class GuiTurtle extends HandledScreen { } @Override - protected void init() { + protected void init() + { super.init(); - this.client.keyboard.setRepeatEvents(true); + this.client.keyboard.setRepeatEvents( true ); int termPxWidth = ComputerCraft.turtleTermWidth * FixedWidthFontRenderer.FONT_WIDTH; int termPxHeight = ComputerCraft.turtleTermHeight * FixedWidthFontRenderer.FONT_HEIGHT; - this.terminal = new WidgetTerminal(this.client, () -> this.m_computer, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight, 2, 2, 2, 2); - this.terminalWrapper = new WidgetWrapper(this.terminal, 2 + 8 + this.x, 2 + 8 + this.y, termPxWidth, termPxHeight); + this.terminal = new WidgetTerminal( this.client, () -> this.m_computer, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight, 2, 2, 2, 2 ); + this.terminalWrapper = new WidgetWrapper( this.terminal, 2 + 8 + this.x, 2 + 8 + this.y, termPxWidth, termPxHeight ); - this.children.add(this.terminalWrapper); - this.setFocused(this.terminalWrapper); + this.children.add( this.terminalWrapper ); + this.setFocused( this.terminalWrapper ); } @Override - public void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(stack); - super.render(stack, mouseX, mouseY, partialTicks); - this.drawMouseoverTooltip(stack, mouseX, mouseY); + public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) + { + this.renderBackground( stack ); + super.render( stack, mouseX, mouseY, partialTicks ); + this.drawMouseoverTooltip( stack, mouseX, mouseY ); } @Override - protected void drawForeground(@Nonnull MatrixStack transform, int mouseX, int mouseY) { + protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) + { // Skip rendering labels. } @Override - protected void drawBackground(@Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY) { + protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) + { // Draw term Identifier texture = this.m_family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; - this.terminal.draw(this.terminalWrapper.getX(), this.terminalWrapper.getY()); + this.terminal.draw( this.terminalWrapper.getX(), this.terminalWrapper.getY() ); // Draw border/inventory - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F ); this.client.getTextureManager() - .bindTexture(texture); - this.drawTexture(transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight); + .bindTexture( texture ); + this.drawTexture( transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight ); // Draw selection slot int slot = this.m_container.getSelectedSlot(); - if (slot >= 0) { + if( slot >= 0 ) + { int slotX = slot % 4; int slotY = slot / 4; - this.drawTexture(transform, this.x + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, this.y + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, - 0, - 217, - 24, - 24); + this.drawTexture( transform, this.x + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, this.y + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, + 0, + 217, + 24, + 24 ); } } @Override - public boolean mouseDragged(double x, double y, int button, double deltaX, double deltaY) { - return (this.getFocused() != null && this.getFocused().mouseDragged(x, y, button, deltaX, deltaY)) || super.mouseDragged(x, y, button, deltaX, deltaY); + public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) + { + return (this.getFocused() != null && this.getFocused().mouseDragged( x, y, button, deltaX, deltaY )) || super.mouseDragged( x, y, button, deltaX, deltaY ); } @Override - public boolean keyPressed(int key, int scancode, int modifiers) { + public boolean keyPressed( int key, int scancode, int modifiers ) + { // Forward the tab key to the terminal, rather than moving between controls. - if (key == GLFW.GLFW_KEY_TAB && this.getFocused() != null && this.getFocused() == this.terminalWrapper) { - return this.getFocused().keyPressed(key, scancode, modifiers); + if( key == GLFW.GLFW_KEY_TAB && this.getFocused() != null && this.getFocused() == this.terminalWrapper ) + { + return this.getFocused().keyPressed( key, scancode, modifiers ); } - return super.keyPressed(key, scancode, modifiers); + return super.keyPressed( key, scancode, modifiers ); } @Override - public void removed() { + public void removed() + { super.removed(); - this.children.remove(this.terminal); + this.children.remove( this.terminal ); this.terminal = null; - this.client.keyboard.setRepeatEvents(false); + this.client.keyboard.setRepeatEvents( false ); } @Override - public void tick() { + public void tick() + { super.tick(); this.terminal.update(); } diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java index 5899f6f2e..b0ce38000 100644 --- a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java +++ b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java @@ -6,23 +6,23 @@ package dan200.computercraft.client.gui.widgets; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; - -import java.util.BitSet; -import java.util.function.Supplier; - import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.IComputer; -import org.lwjgl.glfw.GLFW; - import net.minecraft.SharedConstants; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Element; +import org.lwjgl.glfw.GLFW; -public class WidgetTerminal implements Element { +import java.util.BitSet; +import java.util.function.Supplier; + +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; + +public class WidgetTerminal implements Element +{ private static final float TERMINATE_TIME = 0.5f; private final MinecraftClient client; @@ -33,7 +33,7 @@ public class WidgetTerminal implements Element { private final int rightMargin; private final int topMargin; private final int bottomMargin; - private final BitSet keysDown = new BitSet(256); + private final BitSet keysDown = new BitSet( 256 ); private boolean focused; private float terminateTimer = -1; private float rebootTimer = -1; @@ -42,8 +42,9 @@ public class WidgetTerminal implements Element { private int lastMouseX = -1; private int lastMouseY = -1; - public WidgetTerminal(MinecraftClient client, Supplier computer, int termWidth, int termHeight, int leftMargin, int rightMargin, - int topMargin, int bottomMargin) { + public WidgetTerminal( MinecraftClient client, Supplier computer, int termWidth, int termHeight, int leftMargin, int rightMargin, + int topMargin, int bottomMargin ) + { this.client = client; this.computer = computer; this.termWidth = termWidth; @@ -55,20 +56,23 @@ public class WidgetTerminal implements Element { } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { + public boolean mouseClicked( double mouseX, double mouseY, int button ) + { ClientComputer computer = this.computer.get(); - if (computer == null || !computer.isColour() || button < 0 || button > 2) { + if( computer == null || !computer.isColour() || button < 0 || button > 2 ) + { return false; } Terminal term = computer.getTerminal(); - if (term != null) { + if( term != null ) + { int charX = (int) (mouseX / FONT_WIDTH); int charY = (int) (mouseY / FONT_HEIGHT); - charX = Math.min(Math.max(charX, 0), term.getWidth() - 1); - charY = Math.min(Math.max(charY, 0), term.getHeight() - 1); + charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); + charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); - computer.mouseClick(button + 1, charX + 1, charY + 1); + computer.mouseClick( button + 1, charX + 1, charY + 1 ); this.lastMouseButton = button; this.lastMouseX = charX; @@ -79,21 +83,25 @@ public class WidgetTerminal implements Element { } @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { + public boolean mouseReleased( double mouseX, double mouseY, int button ) + { ClientComputer computer = this.computer.get(); - if (computer == null || !computer.isColour() || button < 0 || button > 2) { + if( computer == null || !computer.isColour() || button < 0 || button > 2 ) + { return false; } Terminal term = computer.getTerminal(); - if (term != null) { + if( term != null ) + { int charX = (int) (mouseX / FONT_WIDTH); int charY = (int) (mouseY / FONT_HEIGHT); - charX = Math.min(Math.max(charX, 0), term.getWidth() - 1); - charY = Math.min(Math.max(charY, 0), term.getHeight() - 1); + charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); + charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); - if (this.lastMouseButton == button) { - computer.mouseUp(this.lastMouseButton + 1, charX + 1, charY + 1); + if( this.lastMouseButton == button ) + { + computer.mouseUp( this.lastMouseButton + 1, charX + 1, charY + 1 ); this.lastMouseButton = -1; } @@ -105,21 +113,25 @@ public class WidgetTerminal implements Element { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double v2, double v3) { + public boolean mouseDragged( double mouseX, double mouseY, int button, double v2, double v3 ) + { ClientComputer computer = this.computer.get(); - if (computer == null || !computer.isColour() || button < 0 || button > 2) { + if( computer == null || !computer.isColour() || button < 0 || button > 2 ) + { return false; } Terminal term = computer.getTerminal(); - if (term != null) { + if( term != null ) + { int charX = (int) (mouseX / FONT_WIDTH); int charY = (int) (mouseY / FONT_HEIGHT); - charX = Math.min(Math.max(charX, 0), term.getWidth() - 1); - charY = Math.min(Math.max(charY, 0), term.getHeight() - 1); + charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); + charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); - if (button == this.lastMouseButton && (charX != this.lastMouseX || charY != this.lastMouseY)) { - computer.mouseDrag(button + 1, charX + 1, charY + 1); + if( button == this.lastMouseButton && (charX != this.lastMouseX || charY != this.lastMouseY) ) + { + computer.mouseDrag( button + 1, charX + 1, charY + 1 ); this.lastMouseX = charX; this.lastMouseY = charY; } @@ -129,20 +141,23 @@ public class WidgetTerminal implements Element { } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + public boolean mouseScrolled( double mouseX, double mouseY, double delta ) + { ClientComputer computer = this.computer.get(); - if (computer == null || !computer.isColour() || delta == 0) { + if( computer == null || !computer.isColour() || delta == 0 ) + { return false; } Terminal term = computer.getTerminal(); - if (term != null) { + if( term != null ) + { int charX = (int) (mouseX / FONT_WIDTH); int charY = (int) (mouseY / FONT_HEIGHT); - charX = Math.min(Math.max(charX, 0), term.getWidth() - 1); - charY = Math.min(Math.max(charY, 0), term.getHeight() - 1); + charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); + charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); - computer.mouseScroll(delta < 0 ? 1 : -1, charX + 1, charY + 1); + computer.mouseScroll( delta < 0 ? 1 : -1, charX + 1, charY + 1 ); this.lastMouseX = charX; this.lastMouseY = charY; @@ -152,65 +167,82 @@ public class WidgetTerminal implements Element { } @Override - public boolean keyPressed(int key, int scancode, int modifiers) { - if (key == GLFW.GLFW_KEY_ESCAPE) { + public boolean keyPressed( int key, int scancode, int modifiers ) + { + if( key == GLFW.GLFW_KEY_ESCAPE ) + { return false; } - if ((modifiers & GLFW.GLFW_MOD_CONTROL) != 0) { - switch (key) { - case GLFW.GLFW_KEY_T: - if (this.terminateTimer < 0) { - this.terminateTimer = 0; - } - return true; - case GLFW.GLFW_KEY_S: - if (this.shutdownTimer < 0) { - this.shutdownTimer = 0; - } - return true; - case GLFW.GLFW_KEY_R: - if (this.rebootTimer < 0) { - this.rebootTimer = 0; - } - return true; - - case GLFW.GLFW_KEY_V: - // Ctrl+V for paste - String clipboard = this.client.keyboard.getClipboard(); - if (clipboard != null) { - // Clip to the first occurrence of \r or \n - int newLineIndex1 = clipboard.indexOf("\r"); - int newLineIndex2 = clipboard.indexOf("\n"); - if (newLineIndex1 >= 0 && newLineIndex2 >= 0) { - clipboard = clipboard.substring(0, Math.min(newLineIndex1, newLineIndex2)); - } else if (newLineIndex1 >= 0) { - clipboard = clipboard.substring(0, newLineIndex1); - } else if (newLineIndex2 >= 0) { - clipboard = clipboard.substring(0, newLineIndex2); + if( (modifiers & GLFW.GLFW_MOD_CONTROL) != 0 ) + { + switch( key ) + { + case GLFW.GLFW_KEY_T: + if( this.terminateTimer < 0 ) + { + this.terminateTimer = 0; } - - // Filter the string - clipboard = SharedConstants.stripInvalidChars(clipboard); - if (!clipboard.isEmpty()) { - // Clip to 512 characters and queue the event - if (clipboard.length() > 512) { - clipboard = clipboard.substring(0, 512); - } - this.queueEvent("paste", clipboard); - } - return true; - } + case GLFW.GLFW_KEY_S: + if( this.shutdownTimer < 0 ) + { + this.shutdownTimer = 0; + } + return true; + case GLFW.GLFW_KEY_R: + if( this.rebootTimer < 0 ) + { + this.rebootTimer = 0; + } + return true; + + case GLFW.GLFW_KEY_V: + // Ctrl+V for paste + String clipboard = this.client.keyboard.getClipboard(); + if( clipboard != null ) + { + // Clip to the first occurrence of \r or \n + int newLineIndex1 = clipboard.indexOf( "\r" ); + int newLineIndex2 = clipboard.indexOf( "\n" ); + if( newLineIndex1 >= 0 && newLineIndex2 >= 0 ) + { + clipboard = clipboard.substring( 0, Math.min( newLineIndex1, newLineIndex2 ) ); + } + else if( newLineIndex1 >= 0 ) + { + clipboard = clipboard.substring( 0, newLineIndex1 ); + } + else if( newLineIndex2 >= 0 ) + { + clipboard = clipboard.substring( 0, newLineIndex2 ); + } + + // Filter the string + clipboard = SharedConstants.stripInvalidChars( clipboard ); + if( !clipboard.isEmpty() ) + { + // Clip to 512 characters and queue the event + if( clipboard.length() > 512 ) + { + clipboard = clipboard.substring( 0, 512 ); + } + this.queueEvent( "paste", clipboard ); + } + + return true; + } } } - if (key >= 0 && this.terminateTimer < 0 && this.rebootTimer < 0 && this.shutdownTimer < 0) { + if( key >= 0 && this.terminateTimer < 0 && this.rebootTimer < 0 && this.shutdownTimer < 0 ) + { // Queue the "key" event and add to the down set - boolean repeat = this.keysDown.get(key); - this.keysDown.set(key); + boolean repeat = this.keysDown.get( key ); + this.keysDown.set( key ); IComputer computer = this.computer.get(); - if (computer != null) { - computer.keyDown(key, repeat); + if( computer != null ) + { + computer.keyDown( key, repeat ); } } @@ -218,62 +250,73 @@ public class WidgetTerminal implements Element { } @Override - public boolean keyReleased(int key, int scancode, int modifiers) { + public boolean keyReleased( int key, int scancode, int modifiers ) + { // Queue the "key_up" event and remove from the down set - if (key >= 0 && this.keysDown.get(key)) { - this.keysDown.set(key, false); + if( key >= 0 && this.keysDown.get( key ) ) + { + this.keysDown.set( key, false ); IComputer computer = this.computer.get(); - if (computer != null) { - computer.keyUp(key); + if( computer != null ) + { + computer.keyUp( key ); } } - switch (key) { - case GLFW.GLFW_KEY_T: - this.terminateTimer = -1; - break; - case GLFW.GLFW_KEY_R: - this.rebootTimer = -1; - break; - case GLFW.GLFW_KEY_S: - this.shutdownTimer = -1; - break; - case GLFW.GLFW_KEY_LEFT_CONTROL: - case GLFW.GLFW_KEY_RIGHT_CONTROL: - this.terminateTimer = this.rebootTimer = this.shutdownTimer = -1; - break; + switch( key ) + { + case GLFW.GLFW_KEY_T: + this.terminateTimer = -1; + break; + case GLFW.GLFW_KEY_R: + this.rebootTimer = -1; + break; + case GLFW.GLFW_KEY_S: + this.shutdownTimer = -1; + break; + case GLFW.GLFW_KEY_LEFT_CONTROL: + case GLFW.GLFW_KEY_RIGHT_CONTROL: + this.terminateTimer = this.rebootTimer = this.shutdownTimer = -1; + break; } return true; } @Override - public boolean charTyped(char ch, int modifiers) { - if (ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255) // printable chars in byte range + public boolean charTyped( char ch, int modifiers ) + { + if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range { // Queue the "char" event - this.queueEvent("char", Character.toString(ch)); + this.queueEvent( "char", Character.toString( ch ) ); } return true; } @Override - public boolean changeFocus(boolean reversed) { - if (this.focused) { + public boolean changeFocus( boolean reversed ) + { + if( this.focused ) + { // When blurring, we should make all keys go up - for (int key = 0; key < this.keysDown.size(); key++) { - if (this.keysDown.get(key)) { - this.queueEvent("key_up", key); + for( int key = 0; key < this.keysDown.size(); key++ ) + { + if( this.keysDown.get( key ) ) + { + this.queueEvent( "key_up", key ); } } this.keysDown.clear(); // When blurring, we should make the last mouse button go up - if (this.lastMouseButton > 0) { + if( this.lastMouseButton > 0 ) + { IComputer computer = this.computer.get(); - if (computer != null) { - computer.mouseUp(this.lastMouseButton + 1, this.lastMouseX + 1, this.lastMouseY + 1); + if( computer != null ) + { + computer.mouseUp( this.lastMouseButton + 1, this.lastMouseX + 1, this.lastMouseY + 1 ); } this.lastMouseButton = -1; } @@ -285,56 +328,72 @@ public class WidgetTerminal implements Element { } @Override - public boolean isMouseOver(double x, double y) { + public boolean isMouseOver( double x, double y ) + { return true; } - private void queueEvent(String event, Object... args) { + private void queueEvent( String event, Object... args ) + { ClientComputer computer = this.computer.get(); - if (computer != null) { - computer.queueEvent(event, args); + if( computer != null ) + { + computer.queueEvent( event, args ); } } - public void update() { - if (this.terminateTimer >= 0 && this.terminateTimer < TERMINATE_TIME && (this.terminateTimer += 0.05f) > TERMINATE_TIME) { - this.queueEvent("terminate"); + public void update() + { + if( this.terminateTimer >= 0 && this.terminateTimer < TERMINATE_TIME && (this.terminateTimer += 0.05f) > TERMINATE_TIME ) + { + this.queueEvent( "terminate" ); } - if (this.shutdownTimer >= 0 && this.shutdownTimer < TERMINATE_TIME && (this.shutdownTimer += 0.05f) > TERMINATE_TIME) { + if( this.shutdownTimer >= 0 && this.shutdownTimer < TERMINATE_TIME && (this.shutdownTimer += 0.05f) > TERMINATE_TIME ) + { ClientComputer computer = this.computer.get(); - if (computer != null) { + if( computer != null ) + { computer.shutdown(); } } - if (this.rebootTimer >= 0 && this.rebootTimer < TERMINATE_TIME && (this.rebootTimer += 0.05f) > TERMINATE_TIME) { + if( this.rebootTimer >= 0 && this.rebootTimer < TERMINATE_TIME && (this.rebootTimer += 0.05f) > TERMINATE_TIME ) + { ClientComputer computer = this.computer.get(); - if (computer != null) { + if( computer != null ) + { computer.reboot(); } } } - private void queueEvent(String event) { + private void queueEvent( String event ) + { ClientComputer computer = this.computer.get(); - if (computer != null) { - computer.queueEvent(event); + if( computer != null ) + { + computer.queueEvent( event ); } } - public void draw(int originX, int originY) { - synchronized (this.computer) { + public void draw( int originX, int originY ) + { + synchronized( this.computer ) + { // Draw the screen contents ClientComputer computer = this.computer.get(); Terminal terminal = computer != null ? computer.getTerminal() : null; - if (terminal != null) { - FixedWidthFontRenderer.drawTerminal(originX, originY, terminal, !computer.isColour(), this.topMargin, this.bottomMargin, this.leftMargin, - this.rightMargin); - } else { - FixedWidthFontRenderer.drawEmptyTerminal(originX - this.leftMargin, - originY - this.rightMargin, this.termWidth * FONT_WIDTH + this.leftMargin + this.rightMargin, - this.termHeight * FONT_HEIGHT + this.topMargin + this.bottomMargin); + if( terminal != null ) + { + FixedWidthFontRenderer.drawTerminal( originX, originY, terminal, !computer.isColour(), this.topMargin, this.bottomMargin, this.leftMargin, + this.rightMargin ); + } + else + { + FixedWidthFontRenderer.drawEmptyTerminal( originX - this.leftMargin, + originY - this.rightMargin, this.termWidth * FONT_WIDTH + this.leftMargin + this.rightMargin, + this.termHeight * FONT_HEIGHT + this.topMargin + this.bottomMargin ); } } } diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetWrapper.java b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetWrapper.java index 3b8b424ee..3b7da58a8 100644 --- a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetWrapper.java +++ b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetWrapper.java @@ -8,14 +8,16 @@ package dan200.computercraft.client.gui.widgets; import net.minecraft.client.gui.Element; -public class WidgetWrapper implements Element { +public class WidgetWrapper implements Element +{ private final Element listener; private final int x; private final int y; private final int width; private final int height; - public WidgetWrapper(Element listener, int x, int y, int width, int height) { + public WidgetWrapper( Element listener, int x, int y, int width, int height ) + { this.listener = listener; this.x = x; this.y = y; @@ -24,68 +26,81 @@ public class WidgetWrapper implements Element { } @Override - public boolean mouseClicked(double x, double y, int button) { + public boolean mouseClicked( double x, double y, int button ) + { double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseClicked(dx, dy, button); + return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseClicked( dx, dy, button ); } @Override - public boolean mouseReleased(double x, double y, int button) { + public boolean mouseReleased( double x, double y, int button ) + { double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseReleased(dx, dy, button); + return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseReleased( dx, dy, button ); } @Override - public boolean mouseDragged(double x, double y, int button, double deltaX, double deltaY) { + public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) + { double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseDragged(dx, dy, button, deltaX, deltaY); + return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseDragged( dx, dy, button, deltaX, deltaY ); } @Override - public boolean mouseScrolled(double x, double y, double delta) { + public boolean mouseScrolled( double x, double y, double delta ) + { double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseScrolled(dx, dy, delta); + return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.listener.mouseScrolled( dx, dy, delta ); } @Override - public boolean keyPressed(int key, int scancode, int modifiers) { - return this.listener.keyPressed(key, scancode, modifiers); + public boolean keyPressed( int key, int scancode, int modifiers ) + { + return this.listener.keyPressed( key, scancode, modifiers ); } @Override - public boolean keyReleased(int key, int scancode, int modifiers) { - return this.listener.keyReleased(key, scancode, modifiers); + public boolean keyReleased( int key, int scancode, int modifiers ) + { + return this.listener.keyReleased( key, scancode, modifiers ); } @Override - public boolean charTyped(char character, int modifiers) { - return this.listener.charTyped(character, modifiers); + public boolean charTyped( char character, int modifiers ) + { + return this.listener.charTyped( character, modifiers ); } @Override - public boolean changeFocus(boolean b) { - return this.listener.changeFocus(b); + public boolean changeFocus( boolean b ) + { + return this.listener.changeFocus( b ); } @Override - public boolean isMouseOver(double x, double y) { + public boolean isMouseOver( double x, double y ) + { double dx = x - this.x, dy = y - this.y; return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height; } - public int getX() { + public int getX() + { return this.x; } - public int getY() { + public int getY() + { return this.y; } - public int getWidth() { + public int getWidth() + { return this.width; } - public int getHeight() { + public int getHeight() + { return this.height; } } diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index fd1e78f7e..fa7c0a8f1 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -6,16 +6,10 @@ package dan200.computercraft.client.proxy; -import java.util.function.Supplier; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.ClientRegistry; import dan200.computercraft.client.FrameInfo; -import dan200.computercraft.client.gui.GuiComputer; -import dan200.computercraft.client.gui.GuiDiskDrive; -import dan200.computercraft.client.gui.GuiPrinter; -import dan200.computercraft.client.gui.GuiPrintout; -import dan200.computercraft.client.gui.GuiTurtle; +import dan200.computercraft.client.gui.*; import dan200.computercraft.client.render.TileEntityMonitorRenderer; import dan200.computercraft.client.render.TileEntityTurtleRenderer; import dan200.computercraft.client.render.TurtleModelLoader; @@ -33,105 +27,112 @@ import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; - import dan200.computercraft.shared.util.Config; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; -import net.minecraft.client.item.ModelPredicateProvider; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.item.Item; -import net.minecraft.screen.PlayerScreenHandler; -import net.minecraft.util.Identifier; - import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry; import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback; import net.fabricmc.fabric.mixin.object.builder.ModelPredicateProviderRegistrySpecificAccessor; +import net.minecraft.client.item.ModelPredicateProvider; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.item.Item; +import net.minecraft.screen.PlayerScreenHandler; +import net.minecraft.util.Identifier; -@Environment (EnvType.CLIENT) -public final class ComputerCraftProxyClient implements ClientModInitializer { +import java.util.function.Supplier; - private static void initEvents() { +@Environment( EnvType.CLIENT ) +public final class ComputerCraftProxyClient implements ClientModInitializer +{ + + private static void initEvents() + { ClientBlockEntityEvents.BLOCK_ENTITY_UNLOAD.register( ( blockEntity, world ) -> { - if(blockEntity instanceof TileGeneric ) { - ((TileGeneric)blockEntity).onChunkUnloaded(); + if( blockEntity instanceof TileGeneric ) + { + ((TileGeneric) blockEntity).onChunkUnloaded(); } - }); + } ); ClientUnloadWorldEvent.EVENT.register( () -> ClientMonitor.destroyAll() ); // Config - ClientLifecycleEvents.CLIENT_STARTED.register(Config::clientStarted); + ClientLifecycleEvents.CLIENT_STARTED.register( Config::clientStarted ); } @Override - public void onInitializeClient() { + public void onInitializeClient() + { FrameInfo.init(); registerContainers(); // While turtles themselves are not transparent, their upgrades may be. - BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderLayer.getTranslucent()); - BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderLayer.getTranslucent()); + BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderLayer.getTranslucent() ); + BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderLayer.getTranslucent() ); // Monitors' textures have transparent fronts and so count as cutouts. - BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderLayer.getCutout()); - BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderLayer.getCutout()); + BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderLayer.getCutout() ); + BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderLayer.getCutout() ); // Setup TESRs - BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new); - BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new); - BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new); - BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new); + BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new ); + BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new ); + BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new ); + BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new ); - ClientSpriteRegistryCallback.event(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE) - .register(ClientRegistry::onTextureStitchEvent); - ModelLoadingRegistry.INSTANCE.registerAppender(ClientRegistry::onModelBakeEvent); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(loader -> (name, context) -> TurtleModelLoader.INSTANCE.accepts(name) ? - TurtleModelLoader.INSTANCE.loadModel( - name) : null); + ClientSpriteRegistryCallback.event( PlayerScreenHandler.BLOCK_ATLAS_TEXTURE ) + .register( ClientRegistry::onTextureStitchEvent ); + ModelLoadingRegistry.INSTANCE.registerAppender( ClientRegistry::onModelBakeEvent ); + ModelLoadingRegistry.INSTANCE.registerResourceProvider( loader -> ( name, context ) -> TurtleModelLoader.INSTANCE.accepts( name ) ? + TurtleModelLoader.INSTANCE.loadModel( + name ) : null ); - EntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new); + EntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new ); - registerItemProperty("state", - (stack, world, player) -> ItemPocketComputer.getState(stack) - .ordinal(), - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED); - registerItemProperty("state", - (stack, world, player) -> IColouredItem.getColourBasic(stack) != -1 ? 1 : 0, - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED); + registerItemProperty( "state", + ( stack, world, player ) -> ItemPocketComputer.getState( stack ) + .ordinal(), + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED ); + registerItemProperty( "state", + ( stack, world, player ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0, + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED ); ClientRegistry.onItemColours(); initEvents(); } // My IDE doesn't think so, but we do actually need these generics. - private static void registerContainers() { - ScreenRegistry.>register(ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create); - ScreenRegistry.>register(ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, - GuiComputer::createPocket); - ScreenRegistry.register(ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new); + private static void registerContainers() + { + ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create ); + ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, + GuiComputer::createPocket ); + ScreenRegistry.register( ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new ); - ScreenRegistry.register(ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new); - ScreenRegistry.register(ComputerCraftRegistry.ModContainers.DISK_DRIVE, GuiDiskDrive::new); - ScreenRegistry.register(ComputerCraftRegistry.ModContainers.PRINTOUT, GuiPrintout::new); + ScreenRegistry.register( ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new ); + ScreenRegistry.register( ComputerCraftRegistry.ModContainers.DISK_DRIVE, GuiDiskDrive::new ); + ScreenRegistry.register( ComputerCraftRegistry.ModContainers.PRINTOUT, GuiPrintout::new ); - ScreenRegistry.>register(ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, - GuiComputer::createView); + ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, + GuiComputer::createView ); } @SafeVarargs - private static void registerItemProperty(String name, ModelPredicateProvider getter, Supplier... items) { - Identifier id = new Identifier(ComputerCraft.MOD_ID, name); - for (Supplier item : items) { - ModelPredicateProviderRegistrySpecificAccessor.callRegister(item.get(), id, getter); + private static void registerItemProperty( String name, ModelPredicateProvider getter, Supplier... items ) + { + Identifier id = new Identifier( ComputerCraft.MOD_ID, name ); + for( Supplier item : items ) + { + ModelPredicateProviderRegistrySpecificAccessor.callRegister( item.get(), id, getter ); } } } diff --git a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java index 032393650..1c1190d1f 100644 --- a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java @@ -10,7 +10,8 @@ import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.modem.wired.BlockCable; import dan200.computercraft.shared.peripheral.modem.wired.CableShapes; import dan200.computercraft.shared.util.WorldUtil; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.Camera; @@ -23,48 +24,49 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.World; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -@Environment (EnvType.CLIENT) -public final class CableHighlightRenderer { - private CableHighlightRenderer() { +@Environment( EnvType.CLIENT ) +public final class CableHighlightRenderer +{ + private CableHighlightRenderer() + { } /** * Draw an outline for a specific part of a cable "Multipart". */ - public static boolean drawHighlight(MatrixStack stack, VertexConsumer consumer, Entity entity, double d, double e, double f, BlockPos pos, - BlockState state) { + public static boolean drawHighlight( MatrixStack stack, VertexConsumer consumer, Entity entity, double d, double e, double f, BlockPos pos, + BlockState state ) + { World world = entity.getEntityWorld(); Camera info = MinecraftClient.getInstance().gameRenderer.getCamera(); // We only care about instances with both cable and modem. - if (state.getBlock() != ComputerCraftRegistry.ModBlocks.CABLE || state.get(BlockCable.MODEM) - .getFacing() == null || !state.get(BlockCable.CABLE)) { + if( state.getBlock() != ComputerCraftRegistry.ModBlocks.CABLE || state.get( BlockCable.MODEM ) + .getFacing() == null || !state.get( BlockCable.CABLE ) ) + { return false; } - VoxelShape shape = WorldUtil.isVecInside(CableShapes.getModemShape(state), - new Vec3d(d, e, f).subtract(pos.getX(), - pos.getY(), - pos.getZ())) ? CableShapes.getModemShape(state) : CableShapes.getCableShape( - state); + VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), + new Vec3d( d, e, f ).subtract( pos.getX(), + pos.getY(), + pos.getZ() ) ) ? CableShapes.getModemShape( state ) : CableShapes.getCableShape( + state ); Vec3d cameraPos = info.getPos(); double xOffset = pos.getX() - cameraPos.getX(); double yOffset = pos.getY() - cameraPos.getY(); double zOffset = pos.getZ() - cameraPos.getZ(); Matrix4f matrix4f = stack.peek() - .getModel(); - shape.forEachEdge((x1, y1, z1, x2, y2, z2) -> { - consumer.vertex(matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset)) - .color(0, 0, 0, 0.4f) - .next(); - consumer.vertex(matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset)) - .color(0, 0, 0, 0.4f) - .next(); - }); + .getModel(); + shape.forEachEdge( ( x1, y1, z1, x2, y2, z2 ) -> { + consumer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) ) + .color( 0, 0, 0, 0.4f ) + .next(); + consumer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) ) + .color( 0, 0, 0, 0.4f ) + .next(); + } ); return true; } diff --git a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java index 8efd22185..d28e67d31 100644 --- a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java @@ -5,25 +5,25 @@ */ package dan200.computercraft.client.render; -import javax.annotation.Nonnull; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ComputerFamily; -import org.lwjgl.opengl.GL11; - import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexFormats; import net.minecraft.util.Identifier; import net.minecraft.util.math.Matrix4f; +import org.lwjgl.opengl.GL11; -public class ComputerBorderRenderer { - public static final Identifier BACKGROUND_NORMAL = new Identifier(ComputerCraft.MOD_ID, "textures/gui/corners_normal.png"); - public static final Identifier BACKGROUND_ADVANCED = new Identifier(ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png"); - public static final Identifier BACKGROUND_COMMAND = new Identifier(ComputerCraft.MOD_ID, "textures/gui/corners_command.png"); - public static final Identifier BACKGROUND_COLOUR = new Identifier(ComputerCraft.MOD_ID, "textures/gui/corners_colour.png"); +import javax.annotation.Nonnull; + +public class ComputerBorderRenderer +{ + public static final Identifier BACKGROUND_NORMAL = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" ); + public static final Identifier BACKGROUND_ADVANCED = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" ); + public static final Identifier BACKGROUND_COMMAND = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" ); + public static final Identifier BACKGROUND_COLOUR = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" ); /** * The margin between the terminal and its border. */ @@ -44,7 +44,8 @@ public class ComputerBorderRenderer { public static final int LIGHT_HEIGHT = 8; private static final float TEX_SCALE = 1 / 256.0f; - static { + static + { IDENTITY.loadIdentity(); } @@ -53,7 +54,8 @@ public class ComputerBorderRenderer { private final int z; private final float r, g, b; - public ComputerBorderRenderer(Matrix4f transform, VertexConsumer builder, int z, float r, float g, float b) { + public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, float r, float g, float b ) + { this.transform = transform; this.builder = builder; this.z = z; @@ -64,34 +66,39 @@ public class ComputerBorderRenderer { @Nonnull - public static Identifier getTexture(@Nonnull ComputerFamily family) { - switch (family) { - case NORMAL: - default: - return BACKGROUND_NORMAL; - case ADVANCED: - return BACKGROUND_ADVANCED; - case COMMAND: - return BACKGROUND_COMMAND; + public static Identifier getTexture( @Nonnull ComputerFamily family ) + { + switch( family ) + { + case NORMAL: + default: + return BACKGROUND_NORMAL; + case ADVANCED: + return BACKGROUND_ADVANCED; + case COMMAND: + return BACKGROUND_COMMAND; } } - public static void render(int x, int y, int z, int width, int height) { + public static void render( int x, int y, int z, int width, int height ) + { Tessellator tessellator = Tessellator.getInstance(); BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE); + buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE ); - render(IDENTITY, buffer, x, y, z, width, height); + render( IDENTITY, buffer, x, y, z, width, height ); RenderSystem.enableAlphaTest(); tessellator.draw(); } - public static void render(Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height) { - render(transform, buffer, x, y, z, width, height, 1, 1, 1); + public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height ) + { + render( transform, buffer, x, y, z, width, height, 1, 1, 1 ); } - public static void render(Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, float r, float g, float b) { + public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, float r, float g, float b ) + { render( transform, buffer, x, y, z, width, height, false, r, g, b ); } @@ -106,13 +113,13 @@ public class ComputerBorderRenderer { int endY = y + height; // Vertical bars - this.renderLine(x - BORDER, y, 0, CORNER_TOP_Y, BORDER, endY - y); - this.renderLine(endX, y, BORDER_RIGHT_X, CORNER_TOP_Y, BORDER, endY - y); + this.renderLine( x - BORDER, y, 0, CORNER_TOP_Y, BORDER, endY - y ); + this.renderLine( endX, y, BORDER_RIGHT_X, CORNER_TOP_Y, BORDER, endY - y ); // Top bar - this.renderLine(x, y - BORDER, 0, 0, endX - x, BORDER); - this.renderCorner(x - BORDER, y - BORDER, CORNER_LEFT_X, CORNER_TOP_Y); - this.renderCorner(endX, y - BORDER, CORNER_RIGHT_X, CORNER_TOP_Y); + this.renderLine( x, y - BORDER, 0, 0, endX - x, BORDER ); + this.renderCorner( x - BORDER, y - BORDER, CORNER_LEFT_X, CORNER_TOP_Y ); + this.renderCorner( endX, y - BORDER, CORNER_RIGHT_X, CORNER_TOP_Y ); // Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the // pocket computer's lights). @@ -124,40 +131,44 @@ public class ComputerBorderRenderer { } else { - this.renderLine(x, endY, 0, BORDER, endX - x, BORDER); - this.renderCorner(x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y); - this.renderCorner(endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y); + this.renderLine( x, endY, 0, BORDER, endX - x, BORDER ); + this.renderCorner( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y ); + this.renderCorner( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y ); } } - private void renderLine(int x, int y, int u, int v, int width, int height) { - this.renderTexture(x, y, u, v, width, height, BORDER, BORDER); + private void renderLine( int x, int y, int u, int v, int width, int height ) + { + this.renderTexture( x, y, u, v, width, height, BORDER, BORDER ); } - private void renderCorner(int x, int y, int u, int v) { - this.renderTexture(x, y, u, v, BORDER, BORDER, BORDER, BORDER); + private void renderCorner( int x, int y, int u, int v ) + { + this.renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER ); } - private void renderTexture(int x, int y, int u, int v, int width, int height) { - this.renderTexture(x, y, u, v, width, height, width, height); + private void renderTexture( int x, int y, int u, int v, int width, int height ) + { + this.renderTexture( x, y, u, v, width, height, width, height ); } - private void renderTexture(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { - this.builder.vertex(this.transform, x, y + height, this.z) - .color(this.r, this.g, this.b, 1.0f) - .texture(u * TEX_SCALE, (v + textureHeight) * TEX_SCALE) - .next(); - this.builder.vertex(this.transform, x + width, y + height, this.z) - .color(this.r, this.g, this.b, 1.0f) - .texture((u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE) - .next(); - this.builder.vertex(this.transform, x + width, y, this.z) - .color(this.r, this.g, this.b, 1.0f) - .texture((u + textureWidth) * TEX_SCALE, v * TEX_SCALE) - .next(); - this.builder.vertex(this.transform, x, y, this.z) - .color(this.r, this.g, this.b, 1.0f) - .texture(u * TEX_SCALE, v * TEX_SCALE) - .next(); + private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight ) + { + this.builder.vertex( this.transform, x, y + height, this.z ) + .color( this.r, this.g, this.b, 1.0f ) + .texture( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ) + .next(); + this.builder.vertex( this.transform, x + width, y + height, this.z ) + .color( this.r, this.g, this.b, 1.0f ) + .texture( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ) + .next(); + this.builder.vertex( this.transform, x + width, y, this.z ) + .color( this.r, this.g, this.b, 1.0f ) + .texture( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ) + .next(); + this.builder.vertex( this.transform, x, y, this.z ) + .color( this.r, this.g, this.b, 1.0f ) + .texture( u * TEX_SCALE, v * TEX_SCALE ) + .next(); } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java index 8eb76f6d0..502ebce10 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java @@ -7,7 +7,8 @@ package dan200.computercraft.client.render; import dan200.computercraft.fabric.mixin.HeldItemRendererAccess; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.HeldItemRenderer; @@ -19,28 +20,30 @@ import net.minecraft.util.Arm; import net.minecraft.util.Hand; import net.minecraft.util.math.MathHelper; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -@Environment (EnvType.CLIENT) -public abstract class ItemMapLikeRenderer { - public void renderItemFirstPerson(MatrixStack transform, VertexConsumerProvider render, int lightTexture, Hand hand, float pitch, float equipProgress - , float swingProgress, ItemStack stack) { +@Environment( EnvType.CLIENT ) +public abstract class ItemMapLikeRenderer +{ + public void renderItemFirstPerson( MatrixStack transform, VertexConsumerProvider render, int lightTexture, Hand hand, float pitch, float equipProgress + , float swingProgress, ItemStack stack ) + { PlayerEntity player = MinecraftClient.getInstance().player; transform.push(); - if (hand == Hand.MAIN_HAND && player.getOffHandStack() - .isEmpty()) { - this.renderItemFirstPersonCenter(transform, render, lightTexture, pitch, equipProgress, swingProgress, stack); - } else { - this.renderItemFirstPersonSide(transform, - render, - lightTexture, - hand == Hand.MAIN_HAND ? player.getMainArm() : player.getMainArm() - .getOpposite(), - equipProgress, - swingProgress, - stack); + if( hand == Hand.MAIN_HAND && player.getOffHandStack() + .isEmpty() ) + { + this.renderItemFirstPersonCenter( transform, render, lightTexture, pitch, equipProgress, swingProgress, stack ); + } + else + { + this.renderItemFirstPersonSide( transform, + render, + lightTexture, + hand == Hand.MAIN_HAND ? player.getMainArm() : player.getMainArm() + .getOpposite(), + equipProgress, + swingProgress, + stack ); } transform.pop(); } @@ -48,85 +51,89 @@ public abstract class ItemMapLikeRenderer { /** * Render an item in the middle of the screen. * - * @param transform The matrix transformation stack - * @param render The buffer to render to + * @param transform The matrix transformation stack + * @param render The buffer to render to * @param combinedLight The current light level - * @param pitch The pitch of the player + * @param pitch The pitch of the player * @param equipProgress The equip progress of this item * @param swingProgress The swing progress of this item - * @param stack The stack to render + * @param stack The stack to render */ - private void renderItemFirstPersonCenter(MatrixStack transform, VertexConsumerProvider render, int combinedLight, float pitch, float equipProgress, - float swingProgress, ItemStack stack) { + private void renderItemFirstPersonCenter( MatrixStack transform, VertexConsumerProvider render, int combinedLight, float pitch, float equipProgress, + float swingProgress, ItemStack stack ) + { MinecraftClient minecraft = MinecraftClient.getInstance(); HeldItemRenderer renderer = minecraft.getHeldItemRenderer(); // Setup the appropriate transformations. This is just copied from the // corresponding method in ItemRenderer. - float swingRt = MathHelper.sqrt(swingProgress); - float tX = -0.2f * MathHelper.sin(swingProgress * (float) Math.PI); - float tZ = -0.4f * MathHelper.sin(swingRt * (float) Math.PI); - transform.translate(0, -tX / 2, tZ); + float swingRt = MathHelper.sqrt( swingProgress ); + float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI ); + float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI ); + transform.translate( 0, -tX / 2, tZ ); HeldItemRendererAccess access = (HeldItemRendererAccess) renderer; - float pitchAngle = access.callGetMapAngle(pitch); - transform.translate(0, 0.04F + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f); - transform.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(pitchAngle * -85.0f)); - if (!minecraft.player.isInvisible()) { + float pitchAngle = access.callGetMapAngle( pitch ); + transform.translate( 0, 0.04F + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f ); + transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( pitchAngle * -85.0f ) ); + if( !minecraft.player.isInvisible() ) + { transform.push(); - transform.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(90.0F)); - access.callRenderArm(transform, render, combinedLight, Arm.RIGHT); - access.callRenderArm(transform, render, combinedLight, Arm.LEFT); + transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 90.0F ) ); + access.callRenderArm( transform, render, combinedLight, Arm.RIGHT ); + access.callRenderArm( transform, render, combinedLight, Arm.LEFT ); transform.pop(); } - float rX = MathHelper.sin(swingRt * (float) Math.PI); - transform.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(rX * 20.0F)); - transform.scale(2.0F, 2.0F, 2.0F); + float rX = MathHelper.sin( swingRt * (float) Math.PI ); + transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( rX * 20.0F ) ); + transform.scale( 2.0F, 2.0F, 2.0F ); - this.renderItem(transform, render, stack); + this.renderItem( transform, render, stack ); } /** * Renders the item to one side of the player. * - * @param transform The matrix transformation stack - * @param render The buffer to render to + * @param transform The matrix transformation stack + * @param render The buffer to render to * @param combinedLight The current light level - * @param side The side to render on + * @param side The side to render on * @param equipProgress The equip progress of this item * @param swingProgress The swing progress of this item - * @param stack The stack to render + * @param stack The stack to render */ - private void renderItemFirstPersonSide(MatrixStack transform, VertexConsumerProvider render, int combinedLight, Arm side, float equipProgress, - float swingProgress, ItemStack stack) { + private void renderItemFirstPersonSide( MatrixStack transform, VertexConsumerProvider render, int combinedLight, Arm side, float equipProgress, + float swingProgress, ItemStack stack ) + { MinecraftClient minecraft = MinecraftClient.getInstance(); float offset = side == Arm.RIGHT ? 1f : -1f; - transform.translate(offset * 0.125f, -0.125f, 0f); + transform.translate( offset * 0.125f, -0.125f, 0f ); // If the player is not invisible then render a single arm - if (!minecraft.player.isInvisible()) { + if( !minecraft.player.isInvisible() ) + { transform.push(); - transform.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(offset * 10f)); - ((HeldItemRendererAccess)minecraft.getHeldItemRenderer()) - .callRenderArmHoldingItem(transform, render, combinedLight, equipProgress, swingProgress, side); + transform.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( offset * 10f ) ); + ((HeldItemRendererAccess) minecraft.getHeldItemRenderer()) + .callRenderArmHoldingItem( transform, render, combinedLight, equipProgress, swingProgress, side ); transform.pop(); } // Setup the appropriate transformations. This is just copied from the // corresponding method in ItemRenderer. transform.push(); - transform.translate(offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f); - float f1 = MathHelper.sqrt(swingProgress); - float f2 = MathHelper.sin(f1 * (float) Math.PI); + transform.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f ); + float f1 = MathHelper.sqrt( swingProgress ); + float f2 = MathHelper.sin( f1 * (float) Math.PI ); float f3 = -0.5f * f2; - float f4 = 0.4f * MathHelper.sin(f1 * ((float) Math.PI * 2f)); - float f5 = -0.3f * MathHelper.sin(swingProgress * (float) Math.PI); - transform.translate(offset * f3, f4 - 0.3f * f2, f5); - transform.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(f2 * -45f)); - transform.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(offset * f2 * -30f)); + float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) ); + float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI ); + transform.translate( offset * f3, f4 - 0.3f * f2, f5 ); + transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( f2 * -45f ) ); + transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( offset * f2 * -30f ) ); - this.renderItem(transform, render, stack); + this.renderItem( transform, render, stack ); transform.pop(); } @@ -135,8 +142,8 @@ public abstract class ItemMapLikeRenderer { * The main rendering method for the item. * * @param transform The matrix transformation stack - * @param render The buffer to render to - * @param stack The stack to render + * @param render The buffer to render to + * @param stack The stack to render */ - protected abstract void renderItem(MatrixStack transform, VertexConsumerProvider render, ItemStack stack); + protected abstract void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ); } diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java index e0849849f..e073820cb 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java @@ -6,12 +6,6 @@ package dan200.computercraft.client.render; -import static dan200.computercraft.client.render.ComputerBorderRenderer.*; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; -import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.FixedWidthFontRenderer; @@ -20,8 +14,6 @@ import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.util.Colour; -import org.lwjgl.opengl.GL11; - import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Tessellator; @@ -31,28 +23,37 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.Vector3f; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Matrix4f; +import org.lwjgl.opengl.GL11; +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; import static dan200.computercraft.client.render.ComputerBorderRenderer.*; /** * Emulates map rendering for pocket computers. */ -public final class ItemPocketRenderer extends ItemMapLikeRenderer { +public final class ItemPocketRenderer extends ItemMapLikeRenderer +{ public static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer(); - private ItemPocketRenderer() { + private ItemPocketRenderer() + { } @Override - protected void renderItem(MatrixStack transform, VertexConsumerProvider render, ItemStack stack) { - ClientComputer computer = ItemPocketComputer.createClientComputer(stack); + protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) + { + ClientComputer computer = ItemPocketComputer.createClientComputer( stack ); Terminal terminal = computer == null ? null : computer.getTerminal(); int termWidth, termHeight; - if (terminal == null) { + if( terminal == null ) + { termWidth = ComputerCraft.pocketTermWidth; termHeight = ComputerCraft.pocketTermHeight; - } else { + } + else + { termWidth = terminal.getWidth(); termHeight = terminal.getHeight(); } @@ -63,44 +64,49 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer { // Setup various transformations. Note that these are partially adapted from the corresponding method // in ItemRenderer transform.push(); - transform.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(180f)); - transform.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(180f)); - transform.scale(0.5f, 0.5f, 0.5f); + transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 180f ) ); + transform.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); + transform.scale( 0.5f, 0.5f, 0.5f ); - float scale = 0.75f / Math.max(width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT); - transform.scale(scale, scale, 0); - transform.translate(-0.5 * width, -0.5 * height, 0); + float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT ); + transform.scale( scale, scale, 0 ); + transform.translate( -0.5 * width, -0.5 * height, 0 ); // Render the main frame ItemPocketComputer item = (ItemPocketComputer) stack.getItem(); ComputerFamily family = item.getFamily(); - int frameColour = item.getColour(stack); + int frameColour = item.getColour( stack ); Matrix4f matrix = transform.peek() - .getModel(); - renderFrame(matrix, family, frameColour, width, height); + .getModel(); + renderFrame( matrix, family, frameColour, width, height ); // Render the light - int lightColour = ItemPocketComputer.getLightState(stack); - if (lightColour == -1) { + int lightColour = ItemPocketComputer.getLightState( stack ); + if( lightColour == -1 ) + { lightColour = Colour.BLACK.getHex(); } - renderLight(matrix, lightColour, width, height); + renderLight( matrix, lightColour, width, height ); - if (computer != null && terminal != null) { - FixedWidthFontRenderer.drawTerminal(matrix, MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN); - } else { - FixedWidthFontRenderer.drawEmptyTerminal(matrix, 0, 0, width, height); + if( computer != null && terminal != null ) + { + FixedWidthFontRenderer.drawTerminal( matrix, MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); + } + else + { + FixedWidthFontRenderer.drawEmptyTerminal( matrix, 0, 0, width, height ); } transform.pop(); } - private static void renderFrame(Matrix4f transform, ComputerFamily family, int colour, int width, int height) { + private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height ) + { RenderSystem.enableBlend(); MinecraftClient.getInstance() - .getTextureManager() - .bindTexture(colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture(family)); + .getTextureManager() + .bindTexture( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) ); float r = ((colour >>> 16) & 0xFF) / 255.0f; float g = ((colour >>> 8) & 0xFF) / 255.0f; @@ -108,14 +114,15 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer { Tessellator tessellator = Tessellator.getInstance(); BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE); + buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE ); - ComputerBorderRenderer.render(transform, buffer, 0, 0, 0, width, height, true, r, g, b); + ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b ); tessellator.draw(); } - private static void renderLight(Matrix4f transform, int colour, int width, int height) { + private static void renderLight( Matrix4f transform, int colour, int width, int height ) + { RenderSystem.disableTexture(); float r = ((colour >>> 16) & 0xFF) / 255.0f; @@ -124,19 +131,19 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer { Tessellator tessellator = Tessellator.getInstance(); BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); - buffer.vertex(transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0) - .color(r, g, b, 1.0f) - .next(); - buffer.vertex(transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, 0) - .color(r, g, b, 1.0f) - .next(); - buffer.vertex(transform, width, height + BORDER / 2.0f, 0) - .color(r, g, b, 1.0f) - .next(); - buffer.vertex(transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0) - .color(r, g, b, 1.0f) - .next(); + buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR ); + buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ) + .color( r, g, b, 1.0f ) + .next(); + buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ) + .color( r, g, b, 1.0f ) + .next(); + buffer.vertex( transform, width, height + BORDER / 2.0f, 0 ) + .color( r, g, b, 1.0f ) + .next(); + buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0 ) + .color( r, g, b, 1.0f ) + .next(); tessellator.draw(); RenderSystem.enableTexture(); diff --git a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java index dd54cae61..5878c61d3 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java @@ -6,88 +6,90 @@ package dan200.computercraft.client.render; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.render.PrintoutRenderer.COVER_SIZE; -import static dan200.computercraft.client.render.PrintoutRenderer.X_TEXT_MARGIN; -import static dan200.computercraft.client.render.PrintoutRenderer.Y_TEXT_MARGIN; -import static dan200.computercraft.client.render.PrintoutRenderer.drawBorder; -import static dan200.computercraft.client.render.PrintoutRenderer.drawText; -import static dan200.computercraft.client.render.PrintoutRenderer.offsetAt; -import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; -import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH; - import dan200.computercraft.shared.media.items.ItemPrintout; - import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.Vector3f; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Matrix4f; +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; +import static dan200.computercraft.client.render.PrintoutRenderer.*; +import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; +import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH; + /** * Emulates map and item-frame rendering for printouts. */ -public final class ItemPrintoutRenderer extends ItemMapLikeRenderer { +public final class ItemPrintoutRenderer extends ItemMapLikeRenderer +{ public static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer(); - private ItemPrintoutRenderer() { + private ItemPrintoutRenderer() + { } @Override - protected void renderItem(MatrixStack transform, VertexConsumerProvider render, ItemStack stack) { - transform.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(180f)); - transform.scale(0.42f, 0.42f, -0.42f); - transform.translate(-0.5f, -0.48f, 0.0f); + protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) + { + transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( 180f ) ); + transform.scale( 0.42f, 0.42f, -0.42f ); + transform.translate( -0.5f, -0.48f, 0.0f ); - drawPrintout(transform, render, stack); + drawPrintout( transform, render, stack ); } - private static void drawPrintout(MatrixStack transform, VertexConsumerProvider render, ItemStack stack) { - int pages = ItemPrintout.getPageCount(stack); + private static void drawPrintout( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) + { + int pages = ItemPrintout.getPageCount( stack ); boolean book = ((ItemPrintout) stack.getItem()).getType() == ItemPrintout.Type.BOOK; double width = LINE_MAX_LENGTH * FONT_WIDTH + X_TEXT_MARGIN * 2; double height = LINES_PER_PAGE * FONT_HEIGHT + Y_TEXT_MARGIN * 2; // Non-books will be left aligned - if (!book) { - width += offsetAt(pages); + if( !book ) + { + width += offsetAt( pages ); } double visualWidth = width, visualHeight = height; // Meanwhile books will be centred - if (book) { - visualWidth += 2 * COVER_SIZE + 2 * offsetAt(pages); + if( book ) + { + visualWidth += 2 * COVER_SIZE + 2 * offsetAt( pages ); visualHeight += 2 * COVER_SIZE; } - double max = Math.max(visualHeight, visualWidth); + double max = Math.max( visualHeight, visualWidth ); // Scale the printout to fit correctly. float scale = (float) (1.0 / max); - transform.scale(scale, scale, scale); - transform.translate((max - width) / 2.0, (max - height) / 2.0, 0.0); + transform.scale( scale, scale, scale ); + transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 ); Matrix4f matrix = transform.peek() - .getModel(); - drawBorder(matrix, render, 0, 0, -0.01f, 0, pages, book); - drawText(matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText(stack), ItemPrintout.getColours(stack)); + .getModel(); + drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book ); + drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) ); } - public boolean renderInFrame(MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack) { - if (!(stack.getItem() instanceof ItemPrintout)) { + public boolean renderInFrame( MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack ) + { + if( !(stack.getItem() instanceof ItemPrintout) ) + { return false; } // Move a little bit forward to ensure we're not clipping with the frame - matrixStack.translate(0.0f, 0.0f, -0.001f); - matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(180f)); - matrixStack.scale(0.95f, 0.95f, -0.95f); - matrixStack.translate(-0.5f, -0.5f, 0.0f); + matrixStack.translate( 0.0f, 0.0f, -0.001f ); + matrixStack.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); + matrixStack.scale( 0.95f, 0.95f, -0.95f ); + matrixStack.translate( -0.5f, -0.5f, 0.0f ); - drawPrintout(matrixStack, consumerProvider, stack); + drawPrintout( matrixStack, consumerProvider, stack ); return true; } diff --git a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java index 4dbe7460c..234969e7f 100644 --- a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java +++ b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java @@ -5,10 +5,9 @@ */ package dan200.computercraft.client.render; -import java.util.List; - import dan200.computercraft.fabric.mixin.BakedQuadAccess; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormatElement; import net.minecraft.client.render.VertexFormats; @@ -16,61 +15,71 @@ import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.util.math.Vector4f; import net.minecraft.util.math.Matrix4f; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import java.util.List; /** * Transforms vertices of a model, remaining aware of winding order, and rearranging vertices if needed. */ -@Environment (EnvType.CLIENT) -public final class ModelTransformer { +@Environment( EnvType.CLIENT ) +public final class ModelTransformer +{ private static final Matrix4f identity; - static { + static + { identity = new Matrix4f(); identity.loadIdentity(); } - private ModelTransformer() { + private ModelTransformer() + { } - public static void transformQuadsTo(List output, List input, Matrix4f transform) { - transformQuadsTo(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL, output, input, transform); + public static void transformQuadsTo( List output, List input, Matrix4f transform ) + { + transformQuadsTo( VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL, output, input, transform ); } - public static void transformQuadsTo(VertexFormat format, List output, List input, Matrix4f transform) { - if (transform == null || transform.equals(identity)) { - output.addAll(input); - } else { - for (BakedQuad quad : input) { - output.add(doTransformQuad(format, quad, transform)); + public static void transformQuadsTo( VertexFormat format, List output, List input, Matrix4f transform ) + { + if( transform == null || transform.equals( identity ) ) + { + output.addAll( input ); + } + else + { + for( BakedQuad quad : input ) + { + output.add( doTransformQuad( format, quad, transform ) ); } } } - private static BakedQuad doTransformQuad(VertexFormat format, BakedQuad quad, Matrix4f transform) { + private static BakedQuad doTransformQuad( VertexFormat format, BakedQuad quad, Matrix4f transform ) + { int[] vertexData = quad.getVertexData().clone(); - BakedQuad copy = new BakedQuad(vertexData, -1, quad.getFace(), ((BakedQuadAccess)quad).getSprite(), true); + BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), ((BakedQuadAccess) quad).getSprite(), true ); int offsetBytes = 0; - for (int v = 0; v < 4; ++v) { - for (VertexFormatElement element : format.getElements()) // For each vertex element + for( int v = 0; v < 4; ++v ) + { + for( VertexFormatElement element : format.getElements() ) // For each vertex element { int start = offsetBytes / Integer.BYTES; - if (element.getType() == VertexFormatElement.Type.POSITION && element.getFormat() == VertexFormatElement.Format.FLOAT) // When we find a position element + if( element.getType() == VertexFormatElement.Type.POSITION && element.getFormat() == VertexFormatElement.Format.FLOAT ) // When we find a position element { - Vector4f pos = new Vector4f(Float.intBitsToFloat(vertexData[start]), - Float.intBitsToFloat(vertexData[start+1]), - Float.intBitsToFloat(vertexData[start+2]), - 1); + Vector4f pos = new Vector4f( Float.intBitsToFloat( vertexData[start] ), + Float.intBitsToFloat( vertexData[start + 1] ), + Float.intBitsToFloat( vertexData[start + 2] ), + 1 ); // Transform the position - pos.transform(transform); + pos.transform( transform ); // Insert the position - vertexData[start] = Float.floatToRawIntBits(pos.getX()); - vertexData[start+1] = Float.floatToRawIntBits(pos.getY()); - vertexData[start+2] = Float.floatToRawIntBits(pos.getZ()); + vertexData[start] = Float.floatToRawIntBits( pos.getX() ); + vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() ); + vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() ); } offsetBytes += element.getSize(); } @@ -78,10 +87,12 @@ public final class ModelTransformer { return copy; } - public static BakedQuad transformQuad(VertexFormat format, BakedQuad input, Matrix4f transform) { - if (transform == null || transform.equals(identity)) { + public static BakedQuad transformQuad( VertexFormat format, BakedQuad input, Matrix4f transform ) + { + if( transform == null || transform.equals( identity ) ) + { return input; } - return doTransformQuad(format, input, transform); + return doTransformQuad( format, input, transform ); } } diff --git a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java index 37cf73145..2a5d0e570 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java @@ -6,17 +6,9 @@ package dan200.computercraft.client.render; -import static net.minecraft.util.math.Direction.DOWN; -import static net.minecraft.util.math.Direction.EAST; -import static net.minecraft.util.math.Direction.NORTH; -import static net.minecraft.util.math.Direction.SOUTH; -import static net.minecraft.util.math.Direction.UP; -import static net.minecraft.util.math.Direction.WEST; - -import java.util.EnumSet; - import dan200.computercraft.shared.peripheral.monitor.TileMonitor; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; @@ -29,96 +21,118 @@ import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import java.util.EnumSet; + +import static net.minecraft.util.math.Direction.*; /** * Overrides monitor highlighting to only render the outline of the whole monitor, rather than the current block. This means you do not get an * intrusive outline on top of the screen. */ -@Environment (EnvType.CLIENT) -public final class MonitorHighlightRenderer { - private MonitorHighlightRenderer() { +@Environment( EnvType.CLIENT ) +public final class MonitorHighlightRenderer +{ + private MonitorHighlightRenderer() + { } - public static boolean drawHighlight(MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos - , BlockState blockState) { + public static boolean drawHighlight( MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos + , BlockState blockState ) + { // Preserve normal behaviour when crouching. - if (entity.isInSneakingPose()) { + if( entity.isInSneakingPose() ) + { return false; } World world = entity.getEntityWorld(); - BlockEntity tile = world.getBlockEntity(pos); - if (!(tile instanceof TileMonitor)) { + BlockEntity tile = world.getBlockEntity( pos ); + if( !(tile instanceof TileMonitor) ) + { return false; } TileMonitor monitor = (TileMonitor) tile; // Determine which sides are part of the external faces of the monitor, and so which need to be rendered. - EnumSet faces = EnumSet.allOf(Direction.class); + EnumSet faces = EnumSet.allOf( Direction.class ); Direction front = monitor.getFront(); - faces.remove(front); - if (monitor.getXIndex() != 0) { - faces.remove(monitor.getRight() - .getOpposite()); + faces.remove( front ); + if( monitor.getXIndex() != 0 ) + { + faces.remove( monitor.getRight() + .getOpposite() ); } - if (monitor.getXIndex() != monitor.getWidth() - 1) { - faces.remove(monitor.getRight()); + if( monitor.getXIndex() != monitor.getWidth() - 1 ) + { + faces.remove( monitor.getRight() ); } - if (monitor.getYIndex() != 0) { - faces.remove(monitor.getDown() - .getOpposite()); + if( monitor.getYIndex() != 0 ) + { + faces.remove( monitor.getDown() + .getOpposite() ); } - if (monitor.getYIndex() != monitor.getHeight() - 1) { - faces.remove(monitor.getDown()); + if( monitor.getYIndex() != monitor.getHeight() - 1 ) + { + faces.remove( monitor.getDown() ); } Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera() - .getPos(); + .getPos(); matrixStack.push(); - matrixStack.translate(pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ()); + matrixStack.translate( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() ); // I wish I could think of a better way to do this Matrix4f transform = matrixStack.peek() - .getModel(); - if (faces.contains(NORTH) || faces.contains(WEST)) { - line(vertexConsumer, transform, 0, 0, 0, UP); + .getModel(); + if( faces.contains( NORTH ) || faces.contains( WEST ) ) + { + line( vertexConsumer, transform, 0, 0, 0, UP ); } - if (faces.contains(SOUTH) || faces.contains(WEST)) { - line(vertexConsumer, transform, 0, 0, 1, UP); + if( faces.contains( SOUTH ) || faces.contains( WEST ) ) + { + line( vertexConsumer, transform, 0, 0, 1, UP ); } - if (faces.contains(NORTH) || faces.contains(EAST)) { - line(vertexConsumer, transform, 1, 0, 0, UP); + if( faces.contains( NORTH ) || faces.contains( EAST ) ) + { + line( vertexConsumer, transform, 1, 0, 0, UP ); } - if (faces.contains(SOUTH) || faces.contains(EAST)) { - line(vertexConsumer, transform, 1, 0, 1, UP); + if( faces.contains( SOUTH ) || faces.contains( EAST ) ) + { + line( vertexConsumer, transform, 1, 0, 1, UP ); } - if (faces.contains(NORTH) || faces.contains(DOWN)) { - line(vertexConsumer, transform, 0, 0, 0, EAST); + if( faces.contains( NORTH ) || faces.contains( DOWN ) ) + { + line( vertexConsumer, transform, 0, 0, 0, EAST ); } - if (faces.contains(SOUTH) || faces.contains(DOWN)) { - line(vertexConsumer, transform, 0, 0, 1, EAST); + if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) + { + line( vertexConsumer, transform, 0, 0, 1, EAST ); } - if (faces.contains(NORTH) || faces.contains(UP)) { - line(vertexConsumer, transform, 0, 1, 0, EAST); + if( faces.contains( NORTH ) || faces.contains( UP ) ) + { + line( vertexConsumer, transform, 0, 1, 0, EAST ); } - if (faces.contains(SOUTH) || faces.contains(UP)) { - line(vertexConsumer, transform, 0, 1, 1, EAST); + if( faces.contains( SOUTH ) || faces.contains( UP ) ) + { + line( vertexConsumer, transform, 0, 1, 1, EAST ); } - if (faces.contains(WEST) || faces.contains(DOWN)) { - line(vertexConsumer, transform, 0, 0, 0, SOUTH); + if( faces.contains( WEST ) || faces.contains( DOWN ) ) + { + line( vertexConsumer, transform, 0, 0, 0, SOUTH ); } - if (faces.contains(EAST) || faces.contains(DOWN)) { - line(vertexConsumer, transform, 1, 0, 0, SOUTH); + if( faces.contains( EAST ) || faces.contains( DOWN ) ) + { + line( vertexConsumer, transform, 1, 0, 0, SOUTH ); } - if (faces.contains(WEST) || faces.contains(UP)) { - line(vertexConsumer, transform, 0, 1, 0, SOUTH); + if( faces.contains( WEST ) || faces.contains( UP ) ) + { + line( vertexConsumer, transform, 0, 1, 0, SOUTH ); } - if (faces.contains(EAST) || faces.contains(UP)) { - line(vertexConsumer, transform, 1, 1, 0, SOUTH); + if( faces.contains( EAST ) || faces.contains( UP ) ) + { + line( vertexConsumer, transform, 1, 1, 0, SOUTH ); } matrixStack.pop(); @@ -126,12 +140,13 @@ public final class MonitorHighlightRenderer { return true; } - private static void line(VertexConsumer buffer, Matrix4f transform, float x, float y, float z, Direction direction) { - buffer.vertex(transform, x, y, z) - .color(0, 0, 0, 0.4f) - .next(); - buffer.vertex(transform, x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ()) - .color(0, 0, 0, 0.4f) - .next(); + private static void line( VertexConsumer buffer, Matrix4f transform, float x, float y, float z, Direction direction ) + { + buffer.vertex( transform, x, y, z ) + .color( 0, 0, 0, 0.4f ) + .next(); + buffer.vertex( transform, x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ() ) + .color( 0, 0, 0, 0.4f ) + .next(); } } diff --git a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java index 485d307cd..2fc785d17 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java @@ -5,27 +5,27 @@ */ package dan200.computercraft.client.render; -import java.io.InputStream; -import java.nio.FloatBuffer; - import com.google.common.base.Strings; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.shared.util.Palette; +import net.minecraft.client.texture.TextureUtil; +import net.minecraft.util.math.Matrix4f; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20; -import net.minecraft.client.texture.TextureUtil; -import net.minecraft.util.math.Matrix4f; +import java.io.InputStream; +import java.nio.FloatBuffer; -class MonitorTextureBufferShader { +class MonitorTextureBufferShader +{ static final int TEXTURE_INDEX = GL13.GL_TEXTURE3; - private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer(16); - private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer(16 * 3); + private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 ); + private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 ); private static int uniformMv; @@ -39,124 +39,145 @@ class MonitorTextureBufferShader { private static boolean ok; private static int program; - static void setupUniform(Matrix4f transform, int width, int height, Palette palette, boolean greyscale) { + static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale ) + { MATRIX_BUFFER.rewind(); - transform.writeToBuffer(MATRIX_BUFFER); + transform.writeToBuffer( MATRIX_BUFFER ); MATRIX_BUFFER.rewind(); - RenderSystem.glUniformMatrix4(uniformMv, false, MATRIX_BUFFER); + RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER ); - RenderSystem.glUniform1i(uniformWidth, width); - RenderSystem.glUniform1i(uniformHeight, height); + RenderSystem.glUniform1i( uniformWidth, width ); + RenderSystem.glUniform1i( uniformHeight, height ); PALETTE_BUFFER.rewind(); - for (int i = 0; i < 16; i++) { - double[] colour = palette.getColour(i); - if (greyscale) { - float f = FixedWidthFontRenderer.toGreyscale(colour); - PALETTE_BUFFER.put(f) - .put(f) - .put(f); - } else { - PALETTE_BUFFER.put((float) colour[0]) - .put((float) colour[1]) - .put((float) colour[2]); + for( int i = 0; i < 16; i++ ) + { + double[] colour = palette.getColour( i ); + if( greyscale ) + { + float f = FixedWidthFontRenderer.toGreyscale( colour ); + PALETTE_BUFFER.put( f ) + .put( f ) + .put( f ); + } + else + { + PALETTE_BUFFER.put( (float) colour[0] ) + .put( (float) colour[1] ) + .put( (float) colour[2] ); } } PALETTE_BUFFER.flip(); - RenderSystem.glUniform3(uniformPalette, PALETTE_BUFFER); + RenderSystem.glUniform3( uniformPalette, PALETTE_BUFFER ); } - static boolean use() { - if (initialised) { - if (ok) { - GlStateManager.useProgram(program); + static boolean use() + { + if( initialised ) + { + if( ok ) + { + GlStateManager.useProgram( program ); } return ok; } - if (ok = load()) { - GL20.glUseProgram(program); - RenderSystem.glUniform1i(uniformFont, 0); - RenderSystem.glUniform1i(uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0); + if( ok = load() ) + { + GL20.glUseProgram( program ); + RenderSystem.glUniform1i( uniformFont, 0 ); + RenderSystem.glUniform1i( uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0 ); } return ok; } - private static boolean load() { + private static boolean load() + { initialised = true; - try { - int vertexShader = loadShader(GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert"); - int fragmentShader = loadShader(GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag"); + try + { + int vertexShader = loadShader( GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert" ); + int fragmentShader = loadShader( GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag" ); program = GlStateManager.createProgram(); - GlStateManager.attachShader(program, vertexShader); - GlStateManager.attachShader(program, fragmentShader); - GL20.glBindAttribLocation(program, 0, "v_pos"); + GlStateManager.attachShader( program, vertexShader ); + GlStateManager.attachShader( program, fragmentShader ); + GL20.glBindAttribLocation( program, 0, "v_pos" ); - GlStateManager.linkProgram(program); - boolean ok = GlStateManager.getProgram(program, GL20.GL_LINK_STATUS) != 0; - String log = GlStateManager.getProgramInfoLog(program, Short.MAX_VALUE) - .trim(); - if (!Strings.isNullOrEmpty(log)) { - ComputerCraft.log.warn("Problems when linking monitor shader: {}", log); + GlStateManager.linkProgram( program ); + boolean ok = GlStateManager.getProgram( program, GL20.GL_LINK_STATUS ) != 0; + String log = GlStateManager.getProgramInfoLog( program, Short.MAX_VALUE ) + .trim(); + if( !Strings.isNullOrEmpty( log ) ) + { + ComputerCraft.log.warn( "Problems when linking monitor shader: {}", log ); } - GL20.glDetachShader(program, vertexShader); - GL20.glDetachShader(program, fragmentShader); - GlStateManager.deleteShader(vertexShader); - GlStateManager.deleteShader(fragmentShader); + GL20.glDetachShader( program, vertexShader ); + GL20.glDetachShader( program, fragmentShader ); + GlStateManager.deleteShader( vertexShader ); + GlStateManager.deleteShader( fragmentShader ); - if (!ok) { + if( !ok ) + { return false; } - uniformMv = getUniformLocation(program, "u_mv"); - uniformFont = getUniformLocation(program, "u_font"); - uniformWidth = getUniformLocation(program, "u_width"); - uniformHeight = getUniformLocation(program, "u_height"); - uniformTbo = getUniformLocation(program, "u_tbo"); - uniformPalette = getUniformLocation(program, "u_palette"); + uniformMv = getUniformLocation( program, "u_mv" ); + uniformFont = getUniformLocation( program, "u_font" ); + uniformWidth = getUniformLocation( program, "u_width" ); + uniformHeight = getUniformLocation( program, "u_height" ); + uniformTbo = getUniformLocation( program, "u_tbo" ); + uniformPalette = getUniformLocation( program, "u_palette" ); - ComputerCraft.log.info("Loaded monitor shader."); + ComputerCraft.log.info( "Loaded monitor shader." ); return true; - } catch (Exception e) { - ComputerCraft.log.error("Cannot load monitor shaders", e); + } + catch( Exception e ) + { + ComputerCraft.log.error( "Cannot load monitor shaders", e ); return false; } } - private static int loadShader(int kind, String path) { + private static int loadShader( int kind, String path ) + { InputStream stream = TileEntityMonitorRenderer.class.getClassLoader() - .getResourceAsStream(path); - if (stream == null) { - throw new IllegalArgumentException("Cannot find " + path); + .getResourceAsStream( path ); + if( stream == null ) + { + throw new IllegalArgumentException( "Cannot find " + path ); } - String contents = TextureUtil.readAllToString(stream); + String contents = TextureUtil.readAllToString( stream ); - int shader = GlStateManager.createShader(kind); + int shader = GlStateManager.createShader( kind ); - GlStateManager.shaderSource(shader, contents); - GlStateManager.compileShader(shader); + GlStateManager.shaderSource( shader, contents ); + GlStateManager.compileShader( shader ); - boolean ok = GlStateManager.getShader(shader, GL20.GL_COMPILE_STATUS) != 0; - String log = GlStateManager.getShaderInfoLog(shader, Short.MAX_VALUE) - .trim(); - if (!Strings.isNullOrEmpty(log)) { - ComputerCraft.log.warn("Problems when loading monitor shader {}: {}", path, log); + boolean ok = GlStateManager.getShader( shader, GL20.GL_COMPILE_STATUS ) != 0; + String log = GlStateManager.getShaderInfoLog( shader, Short.MAX_VALUE ) + .trim(); + if( !Strings.isNullOrEmpty( log ) ) + { + ComputerCraft.log.warn( "Problems when loading monitor shader {}: {}", path, log ); } - if (!ok) { - throw new IllegalStateException("Cannot compile shader " + path); + if( !ok ) + { + throw new IllegalStateException( "Cannot compile shader " + path ); } return shader; } - private static int getUniformLocation(int program, String name) { - int uniform = GlStateManager.getUniformLocation(program, name); - if (uniform == -1) { - throw new IllegalStateException("Cannot find uniform " + name); + private static int getUniformLocation( int program, String name ) + { + int uniform = GlStateManager.getUniformLocation( program, name ); + if( uniform == -1 ) + { + throw new IllegalStateException( "Cannot find uniform " + name ); } return uniform; } diff --git a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java index 4b09e1106..489506aae 100644 --- a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -6,23 +6,19 @@ package dan200.computercraft.client.render; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; - import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.util.Palette; -import org.lwjgl.opengl.GL11; - -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.RenderPhase; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.render.*; import net.minecraft.util.Identifier; import net.minecraft.util.math.Matrix4f; +import org.lwjgl.opengl.GL11; -public final class PrintoutRenderer { +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; +import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; + +public final class PrintoutRenderer +{ /** * Width of a page. */ @@ -43,7 +39,7 @@ public final class PrintoutRenderer { * Size of the leather cover. */ public static final int COVER_SIZE = 12; - private static final Identifier BG = new Identifier("computercraft", "textures/gui/printout.png"); + private static final Identifier BG = new Identifier( "computercraft", "textures/gui/printout.png" ); private static final float BG_SIZE = 256.0f; /** * Width of the extra page texture. @@ -54,146 +50,160 @@ public final class PrintoutRenderer { private PrintoutRenderer() {} - public static void drawText(Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours) { - VertexConsumer buffer = renderer.getBuffer(FixedWidthFontRenderer.TYPE); - for (int line = 0; line < LINES_PER_PAGE && line < text.length; line++) { - FixedWidthFontRenderer.drawString(transform, - buffer, - x, - y + line * FONT_HEIGHT, - text[start + line], - colours[start + line], - null, - Palette.DEFAULT, - false, - 0, - 0); + public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours ) + { + VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); + for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) + { + FixedWidthFontRenderer.drawString( transform, + buffer, + x, + y + line * FONT_HEIGHT, + text[start + line], + colours[start + line], + null, + Palette.DEFAULT, + false, + 0, + 0 ); } } - public static void drawText(Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, String[] text, String[] colours) { - VertexConsumer buffer = renderer.getBuffer(FixedWidthFontRenderer.TYPE); - for (int line = 0; line < LINES_PER_PAGE && line < text.length; line++) { - FixedWidthFontRenderer.drawString(transform, - buffer, - x, - y + line * FONT_HEIGHT, - new TextBuffer(text[start + line]), - new TextBuffer(colours[start + line]), - null, - Palette.DEFAULT, - false, - 0, - 0); + public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, String[] text, String[] colours ) + { + VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); + for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) + { + FixedWidthFontRenderer.drawString( transform, + buffer, + x, + y + line * FONT_HEIGHT, + new TextBuffer( text[start + line] ), + new TextBuffer( colours[start + line] ), + null, + Palette.DEFAULT, + false, + 0, + 0 ); } } - public static void drawBorder(Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook) { + public static void drawBorder( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook ) + { int leftPages = page; int rightPages = pages - page - 1; - VertexConsumer buffer = renderer.getBuffer(Type.TYPE); + VertexConsumer buffer = renderer.getBuffer( Type.TYPE ); - if (isBook) { + if( isBook ) + { // Border - float offset = offsetAt(pages); + float offset = offsetAt( pages ); float left = x - 4 - offset; float right = x + X_SIZE + offset - 4; // Left and right border - drawTexture(transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2); - drawTexture(transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2); + drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); + drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); // Draw centre panel (just stretched texture, sorry). - drawTexture(transform, - buffer, - x - offset, - y, - z - 0.02f, - X_SIZE + offset * 2, - Y_SIZE, - COVER_X + COVER_SIZE / 2.0f, - COVER_SIZE, - COVER_SIZE, - Y_SIZE); + drawTexture( transform, + buffer, + x - offset, + y, + z - 0.02f, + X_SIZE + offset * 2, + Y_SIZE, + COVER_X + COVER_SIZE / 2.0f, + COVER_SIZE, + COVER_SIZE, + Y_SIZE ); float borderX = left; - while (borderX < right) { - double thisWidth = Math.min(right - borderX, X_SIZE); - drawTexture(transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE); - drawTexture(transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE); + while( borderX < right ) + { + double thisWidth = Math.min( right - borderX, X_SIZE ); + drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE ); + drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE ); borderX += thisWidth; } } // Left half - drawTexture(transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE); - for (int n = 0; n <= leftPages; n++) { - drawTexture(transform, buffer, x - offsetAt(n), y, z - 1e-3f * n, - // Use the left "bold" fold for the outermost page - n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE); + drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE ); + for( int n = 0; n <= leftPages; n++ ) + { + drawTexture( transform, buffer, x - offsetAt( n ), y, z - 1e-3f * n, + // Use the left "bold" fold for the outermost page + n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE ); } // Right half - drawTexture(transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE); - for (int n = 0; n <= rightPages; n++) { - drawTexture(transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt(n), y, z - 1e-3f * n, - // Two folds, then the main page. Use the right "bold" fold for the outermost page. - X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE); + drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE ); + for( int n = 0; n <= rightPages; n++ ) + { + drawTexture( transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n, + // Two folds, then the main page. Use the right "bold" fold for the outermost page. + X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE ); } } - public static float offsetAt(int page) { - return (float) (32 * (1 - Math.pow(1.2, -page))); + public static float offsetAt( int page ) + { + return (float) (32 * (1 - Math.pow( 1.2, -page ))); } - private static void drawTexture(Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height) { - buffer.vertex(matrix, x, y + height, z) - .texture(u / BG_SIZE, (v + height) / BG_SIZE) - .next(); - buffer.vertex(matrix, x + width, y + height, z) - .texture((u + width) / BG_SIZE, (v + height) / BG_SIZE) - .next(); - buffer.vertex(matrix, x + width, y, z) - .texture((u + width) / BG_SIZE, v / BG_SIZE) - .next(); - buffer.vertex(matrix, x, y, z) - .texture(u / BG_SIZE, v / BG_SIZE) - .next(); + private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height ) + { + buffer.vertex( matrix, x, y + height, z ) + .texture( u / BG_SIZE, (v + height) / BG_SIZE ) + .next(); + buffer.vertex( matrix, x + width, y + height, z ) + .texture( (u + width) / BG_SIZE, (v + height) / BG_SIZE ) + .next(); + buffer.vertex( matrix, x + width, y, z ) + .texture( (u + width) / BG_SIZE, v / BG_SIZE ) + .next(); + buffer.vertex( matrix, x, y, z ) + .texture( u / BG_SIZE, v / BG_SIZE ) + .next(); } - private static void drawTexture(Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, - float tWidth, float tHeight) { - buffer.vertex(matrix, x, y + height, z) - .texture(u / BG_SIZE, (v + tHeight) / BG_SIZE) - .next(); - buffer.vertex(matrix, x + width, y + height, z) - .texture((u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE) - .next(); - buffer.vertex(matrix, x + width, y, z) - .texture((u + tWidth) / BG_SIZE, v / BG_SIZE) - .next(); - buffer.vertex(matrix, x, y, z) - .texture(u / BG_SIZE, v / BG_SIZE) - .next(); + private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, + float tWidth, float tHeight ) + { + buffer.vertex( matrix, x, y + height, z ) + .texture( u / BG_SIZE, (v + tHeight) / BG_SIZE ) + .next(); + buffer.vertex( matrix, x + width, y + height, z ) + .texture( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ) + .next(); + buffer.vertex( matrix, x + width, y, z ) + .texture( (u + tWidth) / BG_SIZE, v / BG_SIZE ) + .next(); + buffer.vertex( matrix, x, y, z ) + .texture( u / BG_SIZE, v / BG_SIZE ) + .next(); } - private static final class Type extends RenderPhase { - static final RenderLayer TYPE = RenderLayer.of("printout_background", - VertexFormats.POSITION_TEXTURE, - GL11.GL_QUADS, - 1024, - false, - false, - // useDelegate, needsSorting - RenderLayer.MultiPhaseParameters.builder() - .texture(new RenderPhase.Texture(BG, false, false)) // blur, minimap - .alpha(ONE_TENTH_ALPHA) - .lightmap(DISABLE_LIGHTMAP) - .build(false)); + private static final class Type extends RenderPhase + { + static final RenderLayer TYPE = RenderLayer.of( "printout_background", + VertexFormats.POSITION_TEXTURE, + GL11.GL_QUADS, + 1024, + false, + false, + // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( new RenderPhase.Texture( BG, false, false ) ) // blur, minimap + .alpha( ONE_TENTH_ALPHA ) + .lightmap( DISABLE_LIGHTMAP ) + .build( false ) ); - private Type(String name, Runnable setup, Runnable destroy) { - super(name, setup, destroy); + private Type( String name, Runnable setup, Runnable destroy ) + { + super( name, setup, destroy ); } } } diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java index b096a93df..5390b812a 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java @@ -6,14 +6,6 @@ package dan200.computercraft.client.render; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.getColour; - -import java.nio.ByteBuffer; - -import javax.annotation.Nonnull; - import com.mojang.blaze3d.platform.GlStateManager; import dan200.computercraft.client.FrameInfo; import dan200.computercraft.client.gui.FixedWidthFontRenderer; @@ -24,17 +16,8 @@ import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; import dan200.computercraft.shared.peripheral.monitor.TileMonitor; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.DirectionUtil; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL20; -import org.lwjgl.opengl.GL31; - import net.minecraft.client.gl.VertexBuffer; -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.Tessellator; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.render.*; import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.client.util.GlAllocationUtils; @@ -44,27 +27,40 @@ import net.minecraft.client.util.math.Vector3f; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Matrix4f; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL31; -public class TileEntityMonitorRenderer extends BlockEntityRenderer { +import javax.annotation.Nonnull; +import java.nio.ByteBuffer; + +import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*; + +public class TileEntityMonitorRenderer extends BlockEntityRenderer +{ /** * {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between the monitor frame and contents. */ private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1); private static final Matrix4f IDENTITY = AffineTransformation.identity() - .getMatrix(); + .getMatrix(); private static ByteBuffer tboContents; - public TileEntityMonitorRenderer(BlockEntityRenderDispatcher rendererDispatcher) { - super(rendererDispatcher); + public TileEntityMonitorRenderer( BlockEntityRenderDispatcher rendererDispatcher ) + { + super( rendererDispatcher ); } @Override - public void render(@Nonnull TileMonitor monitor, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer, - int lightmapCoord, int overlayLight) { + public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer, + int lightmapCoord, int overlayLight ) + { // Render from the origin monitor ClientMonitor originTerminal = monitor.getClientMonitor(); - if (originTerminal == null) { + if( originTerminal == null ) + { return; } TileMonitor origin = originTerminal.getOrigin(); @@ -74,7 +70,8 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer // multiple times in a single frame to ensure compatibility with shaders which may run a // pass multiple times. long renderFrame = FrameInfo.getRenderFrame(); - if (originTerminal.lastRenderFrame == renderFrame && !monitorPos.equals(originTerminal.lastRenderPos)) { + if( originTerminal.lastRenderFrame == renderFrame && !monitorPos.equals( originTerminal.lastRenderPos ) ) + { return; } @@ -87,165 +84,179 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer Direction dir = origin.getDirection(); Direction front = origin.getFront(); float yaw = dir.asRotation(); - float pitch = DirectionUtil.toPitchAngle(front); + float pitch = DirectionUtil.toPitchAngle( front ); // Setup initial transform transform.push(); - transform.translate(originPos.getX() - monitorPos.getX() + 0.5, - originPos.getY() - monitorPos.getY() + 0.5, - originPos.getZ() - monitorPos.getZ() + 0.5); + transform.translate( originPos.getX() - monitorPos.getX() + 0.5, + originPos.getY() - monitorPos.getY() + 0.5, + originPos.getZ() - monitorPos.getZ() + 0.5 ); - transform.multiply(Vector3f.NEGATIVE_Y.getDegreesQuaternion(yaw)); - transform.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(pitch)); - transform.translate(-0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN, - origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0, - 0.5); + transform.multiply( Vector3f.NEGATIVE_Y.getDegreesQuaternion( yaw ) ); + transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( pitch ) ); + transform.translate( -0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN, + origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0, + 0.5 ); double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER); double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER); // Draw the contents Terminal terminal = originTerminal.getTerminal(); - if (terminal != null) { + if( terminal != null ) + { // Draw a terminal int width = terminal.getWidth(), height = terminal.getHeight(); int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT; double xScale = xSize / pixelWidth; double yScale = ySize / pixelHeight; transform.push(); - transform.scale((float) xScale, (float) -yScale, 1.0f); + transform.scale( (float) xScale, (float) -yScale, 1.0f ); Matrix4f matrix = transform.peek() - .getModel(); + .getModel(); // Sneaky hack here: we get a buffer now in order to flush existing ones and set up the appropriate // render state. I've no clue how well this'll work in future versions of Minecraft, but it does the trick // for now. - VertexConsumer buffer = renderer.getBuffer(FixedWidthFontRenderer.TYPE); + VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); FixedWidthFontRenderer.TYPE.startDrawing(); - renderTerminal(matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale)); + renderTerminal( matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) ); // We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is // reasonable. - FixedWidthFontRenderer.drawCursor(matrix, buffer, 0, 0, terminal, !originTerminal.isColour()); + FixedWidthFontRenderer.drawCursor( matrix, buffer, 0, 0, terminal, !originTerminal.isColour() ); transform.pop(); - } else { - FixedWidthFontRenderer.drawEmptyTerminal(transform.peek() - .getModel(), - renderer, - -MARGIN, - MARGIN, - (float) (xSize + 2 * MARGIN), - (float) -(ySize + MARGIN * 2)); + } + else + { + FixedWidthFontRenderer.drawEmptyTerminal( transform.peek() + .getModel(), + renderer, + -MARGIN, + MARGIN, + (float) (xSize + 2 * MARGIN), + (float) -(ySize + MARGIN * 2) ); } - FixedWidthFontRenderer.drawBlocker(transform.peek() - .getModel(), - renderer, - (float) -TileMonitor.RENDER_MARGIN, - (float) TileMonitor.RENDER_MARGIN, - (float) (xSize + 2 * TileMonitor.RENDER_MARGIN), - (float) -(ySize + TileMonitor.RENDER_MARGIN * 2)); + FixedWidthFontRenderer.drawBlocker( transform.peek() + .getModel(), + renderer, + (float) -TileMonitor.RENDER_MARGIN, + (float) TileMonitor.RENDER_MARGIN, + (float) (xSize + 2 * TileMonitor.RENDER_MARGIN), + (float) -(ySize + TileMonitor.RENDER_MARGIN * 2) ); transform.pop(); } - private static void renderTerminal(Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin) { + private static void renderTerminal( Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin ) + { Terminal terminal = monitor.getTerminal(); MonitorRenderer renderType = MonitorRenderer.current(); boolean redraw = monitor.pollTerminalChanged(); - if (monitor.createBuffer(renderType)) { + if( monitor.createBuffer( renderType ) ) + { redraw = true; } - switch (renderType) { - case TBO: { - if (!MonitorTextureBufferShader.use()) { - return; - } - - int width = terminal.getWidth(), height = terminal.getHeight(); - int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT; - - if (redraw) { - int size = width * height * 3; - if (tboContents == null || tboContents.capacity() < size) { - tboContents = GlAllocationUtils.allocateByteBuffer(size); + switch( renderType ) + { + case TBO: + { + if( !MonitorTextureBufferShader.use() ) + { + return; } - ByteBuffer monitorBuffer = tboContents; - monitorBuffer.clear(); - for (int y = 0; y < height; y++) { - TextBuffer text = terminal.getLine(y), textColour = terminal.getTextColourLine(y), background = terminal.getBackgroundColourLine(y); - for (int x = 0; x < width; x++) { - monitorBuffer.put((byte) (text.charAt(x) & 0xFF)); - monitorBuffer.put((byte) getColour(textColour.charAt(x), Colour.WHITE)); - monitorBuffer.put((byte) getColour(background.charAt(x), Colour.BLACK)); + int width = terminal.getWidth(), height = terminal.getHeight(); + int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT; + + if( redraw ) + { + int size = width * height * 3; + if( tboContents == null || tboContents.capacity() < size ) + { + tboContents = GlAllocationUtils.allocateByteBuffer( size ); } + + ByteBuffer monitorBuffer = tboContents; + monitorBuffer.clear(); + for( int y = 0; y < height; y++ ) + { + TextBuffer text = terminal.getLine( y ), textColour = terminal.getTextColourLine( y ), background = terminal.getBackgroundColourLine( y ); + for( int x = 0; x < width; x++ ) + { + monitorBuffer.put( (byte) (text.charAt( x ) & 0xFF) ); + monitorBuffer.put( (byte) getColour( textColour.charAt( x ), Colour.WHITE ) ); + monitorBuffer.put( (byte) getColour( background.charAt( x ), Colour.BLACK ) ); + } + } + monitorBuffer.flip(); + + GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer ); + GlStateManager.bufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW ); + GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, 0 ); } - monitorBuffer.flip(); - GlStateManager.bindBuffers(GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer); - GlStateManager.bufferData(GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW); - GlStateManager.bindBuffers(GL31.GL_TEXTURE_BUFFER, 0); - } + // Nobody knows what they're doing! + GlStateManager.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX ); + GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture ); + GlStateManager.activeTexture( GL13.GL_TEXTURE0 ); - // Nobody knows what they're doing! - GlStateManager.activeTexture(MonitorTextureBufferShader.TEXTURE_INDEX); - GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, monitor.tboTexture); - GlStateManager.activeTexture(GL13.GL_TEXTURE0); + MonitorTextureBufferShader.setupUniform( matrix, width, height, terminal.getPalette(), !monitor.isColour() ); - MonitorTextureBufferShader.setupUniform(matrix, width, height, terminal.getPalette(), !monitor.isColour()); - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION); - buffer.vertex(-xMargin, -yMargin, 0) - .next(); - buffer.vertex(-xMargin, pixelHeight + yMargin, 0) - .next(); - buffer.vertex(pixelWidth + xMargin, -yMargin, 0) - .next(); - buffer.vertex(pixelWidth + xMargin, pixelHeight + yMargin, 0) - .next(); - tessellator.draw(); - - GlStateManager.useProgram(0); - break; - } - - case VBO: { - VertexBuffer vbo = monitor.buffer; - if (redraw) { Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder builder = tessellator.getBuffer(); - builder.begin(FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat()); - FixedWidthFontRenderer.drawTerminalWithoutCursor(IDENTITY, - builder, - 0, - 0, - terminal, - !monitor.isColour(), - yMargin, - yMargin, - xMargin, - xMargin); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION ); + buffer.vertex( -xMargin, -yMargin, 0 ) + .next(); + buffer.vertex( -xMargin, pixelHeight + yMargin, 0 ) + .next(); + buffer.vertex( pixelWidth + xMargin, -yMargin, 0 ) + .next(); + buffer.vertex( pixelWidth + xMargin, pixelHeight + yMargin, 0 ) + .next(); + tessellator.draw(); - builder.end(); - vbo.upload(builder); + GlStateManager.useProgram( 0 ); + break; } - vbo.bind(); - FixedWidthFontRenderer.TYPE.getVertexFormat() - .startDrawing(0L); - vbo.draw(matrix, FixedWidthFontRenderer.TYPE.getDrawMode()); - VertexBuffer.unbind(); - FixedWidthFontRenderer.TYPE.getVertexFormat() - .endDrawing(); - break; - } + case VBO: + { + VertexBuffer vbo = monitor.buffer; + if( redraw ) + { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder builder = tessellator.getBuffer(); + builder.begin( FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() ); + FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY, + builder, + 0, + 0, + terminal, + !monitor.isColour(), + yMargin, + yMargin, + xMargin, + xMargin ); + + builder.end(); + vbo.upload( builder ); + } + + vbo.bind(); + FixedWidthFontRenderer.TYPE.getVertexFormat() + .startDrawing( 0L ); + vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getDrawMode() ); + VertexBuffer.unbind(); + FixedWidthFontRenderer.TYPE.getVertexFormat() + .endDrawing(); + break; + } } } } diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java index 8a498cd0a..c657decd7 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java @@ -6,11 +6,6 @@ package dan200.computercraft.client.render; -import java.util.List; -import java.util.Random; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; @@ -19,7 +14,6 @@ import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.Holiday; import dan200.computercraft.shared.util.HolidayUtil; - import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.render.TexturedRenderLayers; @@ -40,47 +34,62 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; -public class TileEntityTurtleRenderer extends BlockEntityRenderer { - private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier("computercraft:turtle_normal", "inventory"); - private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier("computercraft:turtle_advanced", "inventory"); - private static final ModelIdentifier COLOUR_TURTLE_MODEL = new ModelIdentifier("computercraft:turtle_colour", "inventory"); - private static final ModelIdentifier ELF_OVERLAY_MODEL = new ModelIdentifier("computercraft:turtle_elf_overlay", "inventory"); +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Random; - private final Random random = new Random(0); +public class TileEntityTurtleRenderer extends BlockEntityRenderer +{ + private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_normal", "inventory" ); + private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_advanced", "inventory" ); + private static final ModelIdentifier COLOUR_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_colour", "inventory" ); + private static final ModelIdentifier ELF_OVERLAY_MODEL = new ModelIdentifier( "computercraft:turtle_elf_overlay", "inventory" ); - public TileEntityTurtleRenderer(BlockEntityRenderDispatcher renderDispatcher) { - super(renderDispatcher); + private final Random random = new Random( 0 ); + + public TileEntityTurtleRenderer( BlockEntityRenderDispatcher renderDispatcher ) + { + super( renderDispatcher ); } - public static ModelIdentifier getTurtleModel(ComputerFamily family, boolean coloured) { - switch (family) { - case NORMAL: - default: - return coloured ? COLOUR_TURTLE_MODEL : NORMAL_TURTLE_MODEL; - case ADVANCED: - return coloured ? COLOUR_TURTLE_MODEL : ADVANCED_TURTLE_MODEL; + public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured ) + { + switch( family ) + { + case NORMAL: + default: + return coloured ? COLOUR_TURTLE_MODEL : NORMAL_TURTLE_MODEL; + case ADVANCED: + return coloured ? COLOUR_TURTLE_MODEL : ADVANCED_TURTLE_MODEL; } } - public static ModelIdentifier getTurtleOverlayModel(Identifier overlay, boolean christmas) { - if (overlay != null) { - return new ModelIdentifier(overlay, "inventory"); + public static ModelIdentifier getTurtleOverlayModel( Identifier overlay, boolean christmas ) + { + if( overlay != null ) + { + return new ModelIdentifier( overlay, "inventory" ); } - if (christmas) { + if( christmas ) + { return ELF_OVERLAY_MODEL; } return null; } - private static void renderQuads(@Nonnull MatrixStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight, - List quads, int[] tints) { + private static void renderQuads( @Nonnull MatrixStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight, + List quads, int[] tints ) + { MatrixStack.Entry matrix = transform.peek(); - for (BakedQuad bakedquad : quads) { + for( BakedQuad bakedquad : quads ) + { int tint = -1; - if (tints != null && bakedquad.hasColor()) { + if( tints != null && bakedquad.hasColor() ) + { int idx = bakedquad.getColorIndex(); - if (idx >= 0 && idx < tints.length) { + if( idx >= 0 && idx < tints.length ) + { tint = tints[bakedquad.getColorIndex()]; } } @@ -88,52 +97,54 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer { float f = (float) (tint >> 16 & 255) / 255.0F; float f1 = (float) (tint >> 8 & 255) / 255.0F; float f2 = (float) (tint & 255) / 255.0F; - buffer.quad(matrix, - bakedquad, - new float[] { - 1.0F, - 1.0F, - 1.0F, - 1.0F - }, - f, - f1, - f2, - new int[] { - lightmapCoord, - lightmapCoord, - lightmapCoord, - lightmapCoord - }, - overlayLight, - true); + buffer.quad( matrix, + bakedquad, + new float[] { + 1.0F, + 1.0F, + 1.0F, + 1.0F + }, + f, + f1, + f2, + new int[] { + lightmapCoord, + lightmapCoord, + lightmapCoord, + lightmapCoord + }, + overlayLight, + true ); } } @Override - public void render(@Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer, - int lightmapCoord, int overlayLight) { + public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer, + int lightmapCoord, int overlayLight ) + { // Render the label String label = turtle.createProxy() - .getLabel(); + .getLabel(); HitResult hit = this.dispatcher.crosshairTarget; - if (label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos() - .equals(((BlockHitResult) hit).getBlockPos())) { + if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos() + .equals( ((BlockHitResult) hit).getBlockPos() ) ) + { MinecraftClient mc = MinecraftClient.getInstance(); TextRenderer font = mc.textRenderer; transform.push(); - transform.translate(0.5, 1.2, 0.5); - transform.multiply(mc.getEntityRenderDispatcher() - .getRotation()); - transform.scale(-0.025f, -0.025f, 0.025f); + transform.translate( 0.5, 1.2, 0.5 ); + transform.multiply( mc.getEntityRenderDispatcher() + .getRotation() ); + transform.scale( -0.025f, -0.025f, 0.025f ); Matrix4f matrix = transform.peek() - .getModel(); - int opacity = (int) (mc.options.getTextBackgroundOpacity(0.25f) * 255) << 24; - float width = -font.getWidth(label) / 2.0f; - font.draw(label, width, (float) 0, 0x20ffffff, false, matrix, renderer, true, opacity, lightmapCoord); - font.draw(label, width, (float) 0, 0xffffffff, false, matrix, renderer, false, 0, lightmapCoord); + .getModel(); + int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24; + float width = -font.getWidth( label ) / 2.0f; + font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, renderer, true, opacity, lightmapCoord ); + font.draw( label, width, (float) 0, 0xffffffff, false, matrix, renderer, false, 0, lightmapCoord ); transform.pop(); } @@ -141,76 +152,83 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer { transform.push(); // Setup the transform. - Vec3d offset = turtle.getRenderOffset(partialTicks); - float yaw = turtle.getRenderYaw(partialTicks); - transform.translate(offset.x, offset.y, offset.z); + Vec3d offset = turtle.getRenderOffset( partialTicks ); + float yaw = turtle.getRenderYaw( partialTicks ); + transform.translate( offset.x, offset.y, offset.z ); - transform.translate(0.5f, 0.5f, 0.5f); - transform.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(180.0f - yaw)); - if (label != null && (label.equals("Dinnerbone") || label.equals("Grumm"))) { + transform.translate( 0.5f, 0.5f, 0.5f ); + transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) ); + if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) ) + { // Flip the model - transform.scale(1.0f, -1.0f, 1.0f); + transform.scale( 1.0f, -1.0f, 1.0f ); } - transform.translate(-0.5f, -0.5f, -0.5f); + transform.translate( -0.5f, -0.5f, -0.5f ); // Render the turtle int colour = turtle.getColour(); ComputerFamily family = turtle.getFamily(); Identifier overlay = turtle.getOverlay(); - VertexConsumer buffer = renderer.getBuffer(TexturedRenderLayers.getEntityTranslucentCull()); - renderModel(transform, buffer, lightmapCoord, overlayLight, getTurtleModel(family, colour != -1), colour == -1 ? null : new int[] {colour}); + VertexConsumer buffer = renderer.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() ); + renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } ); // Render the overlay - ModelIdentifier overlayModel = getTurtleOverlayModel(overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS); - if (overlayModel != null) { - renderModel(transform, buffer, lightmapCoord, overlayLight, overlayModel, null); + ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS ); + if( overlayModel != null ) + { + renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null ); } // Render the upgrades - renderUpgrade(transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks); - renderUpgrade(transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks); + renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks ); + renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks ); transform.pop(); } - public static void renderUpgrade(@Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle, - TurtleSide side, float f) { - ITurtleUpgrade upgrade = turtle.getUpgrade(side); - if (upgrade == null) { + public static void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle, + TurtleSide side, float f ) + { + ITurtleUpgrade upgrade = turtle.getUpgrade( side ); + if( upgrade == null ) + { return; } transform.push(); - float toolAngle = turtle.getToolRenderAngle(side, f); - transform.translate(0.0f, 0.5f, 0.5f); - transform.multiply(Vector3f.NEGATIVE_X.getDegreesQuaternion(toolAngle)); - transform.translate(0.0f, -0.5f, -0.5f); + float toolAngle = turtle.getToolRenderAngle( side, f ); + transform.translate( 0.0f, 0.5f, 0.5f ); + transform.multiply( Vector3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) ); + transform.translate( 0.0f, -0.5f, -0.5f ); - TransformedModel model = upgrade.getModel(turtle.getAccess(), side); - model.push(transform); - TileEntityTurtleRenderer.renderModel(transform, renderer, lightmapCoord, overlayLight, model.getModel(), null); + TransformedModel model = upgrade.getModel( turtle.getAccess(), side ); + model.push( transform ); + TileEntityTurtleRenderer.renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null ); transform.pop(); transform.pop(); } - public static void renderModel(@Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, - ModelIdentifier modelLocation, int[] tints) { + public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, + ModelIdentifier modelLocation, int[] tints ) + { BakedModelManager modelManager = MinecraftClient.getInstance() - .getItemRenderer() - .getModels() - .getModelManager(); - renderModel(transform, renderer, lightmapCoord, overlayLight, modelManager.getModel(modelLocation), tints); + .getItemRenderer() + .getModels() + .getModelManager(); + renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints ); } - public static void renderModel(@Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, - int[] tints) { + public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, + int[] tints ) + { Random random = new Random(); - random.setSeed(0); - renderQuads(transform, renderer, lightmapCoord, overlayLight, model.getQuads(null, null, random), tints); - for (Direction facing : DirectionUtil.FACINGS) { - renderQuads(transform, renderer, lightmapCoord, overlayLight, model.getQuads(null, facing, random), tints); + random.setSeed( 0 ); + renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints ); + for( Direction facing : DirectionUtil.FACINGS ) + { + renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints ); } } } diff --git a/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java b/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java index 5ff3f23bc..50ae22c5b 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java @@ -6,17 +6,10 @@ package dan200.computercraft.client.render; -import java.util.Arrays; -import java.util.Collection; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -import javax.annotation.Nonnull; - import com.mojang.datafixers.util.Pair; import dan200.computercraft.ComputerCraft; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.ModelBakeSettings; import net.minecraft.client.render.model.ModelLoader; @@ -25,70 +18,84 @@ import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.util.Identifier; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; -@Environment (EnvType.CLIENT) -public final class TurtleModelLoader { +@Environment( EnvType.CLIENT ) +public final class TurtleModelLoader +{ public static final TurtleModelLoader INSTANCE = new TurtleModelLoader(); - private static final Identifier NORMAL_TURTLE_MODEL = new Identifier(ComputerCraft.MOD_ID, "block/turtle_normal"); - private static final Identifier ADVANCED_TURTLE_MODEL = new Identifier(ComputerCraft.MOD_ID, "block/turtle_advanced"); - private static final Identifier COLOUR_TURTLE_MODEL = new Identifier(ComputerCraft.MOD_ID, "block/turtle_colour"); + private static final Identifier NORMAL_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_normal" ); + private static final Identifier ADVANCED_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_advanced" ); + private static final Identifier COLOUR_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_colour" ); - private TurtleModelLoader() { + private TurtleModelLoader() + { } - public boolean accepts(@Nonnull Identifier name) { + public boolean accepts( @Nonnull Identifier name ) + { return name.getNamespace() - .equals(ComputerCraft.MOD_ID) && (name.getPath() - .equals("item/turtle_normal") || name.getPath() - .equals("item/turtle_advanced")); + .equals( ComputerCraft.MOD_ID ) && (name.getPath() + .equals( "item/turtle_normal" ) || name.getPath() + .equals( "item/turtle_advanced" )); } @Nonnull - public UnbakedModel loadModel(@Nonnull Identifier name) { - if (name.getNamespace() - .equals(ComputerCraft.MOD_ID)) { - switch (name.getPath()) { - case "item/turtle_normal": - return new TurtleModel(NORMAL_TURTLE_MODEL); - case "item/turtle_advanced": - return new TurtleModel(ADVANCED_TURTLE_MODEL); + public UnbakedModel loadModel( @Nonnull Identifier name ) + { + if( name.getNamespace() + .equals( ComputerCraft.MOD_ID ) ) + { + switch( name.getPath() ) + { + case "item/turtle_normal": + return new TurtleModel( NORMAL_TURTLE_MODEL ); + case "item/turtle_advanced": + return new TurtleModel( ADVANCED_TURTLE_MODEL ); } } - throw new IllegalStateException("Loader does not accept " + name); + throw new IllegalStateException( "Loader does not accept " + name ); } - private static final class TurtleModel implements UnbakedModel { + private static final class TurtleModel implements UnbakedModel + { private final Identifier family; - private TurtleModel(Identifier family) {this.family = family;} + private TurtleModel( Identifier family ) {this.family = family;} @Override - public Collection getTextureDependencies(Function modelGetter, - Set> missingTextureErrors) { + public Collection getTextureDependencies( Function modelGetter, + Set> missingTextureErrors ) + { return this.getModelDependencies() - .stream() - .flatMap(x -> modelGetter.apply(x) - .getTextureDependencies(modelGetter, missingTextureErrors) - .stream()) - .collect(Collectors.toSet()); + .stream() + .flatMap( x -> modelGetter.apply( x ) + .getTextureDependencies( modelGetter, missingTextureErrors ) + .stream() ) + .collect( Collectors.toSet() ); } @Nonnull @Override - public Collection getModelDependencies() { - return Arrays.asList(this.family, COLOUR_TURTLE_MODEL); + public Collection getModelDependencies() + { + return Arrays.asList( this.family, COLOUR_TURTLE_MODEL ); } @Override - public BakedModel bake(@Nonnull ModelLoader loader, @Nonnull Function spriteGetter, @Nonnull ModelBakeSettings state, - Identifier modelId) { - return new TurtleSmartItemModel(loader.getOrLoadModel(this.family) - .bake(loader, spriteGetter, state, modelId), - loader.getOrLoadModel(COLOUR_TURTLE_MODEL) - .bake(loader, spriteGetter, state, modelId)); + public BakedModel bake( @Nonnull ModelLoader loader, @Nonnull Function spriteGetter, @Nonnull ModelBakeSettings state, + Identifier modelId ) + { + return new TurtleSmartItemModel( loader.getOrLoadModel( this.family ) + .bake( loader, spriteGetter, state, modelId ), + loader.getOrLoadModel( COLOUR_TURTLE_MODEL ) + .bake( loader, spriteGetter, state, modelId ) ); } } } diff --git a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java index e0b1f1cf7..96da1dcc7 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java @@ -6,16 +6,9 @@ package dan200.computercraft.client.render; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.client.TransformedModel; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedQuad; @@ -24,21 +17,23 @@ import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.util.math.Direction; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; +import java.util.*; -@Environment (EnvType.CLIENT) -public class TurtleMultiModel implements BakedModel { +@Environment( EnvType.CLIENT ) +public class TurtleMultiModel implements BakedModel +{ private final BakedModel m_baseModel; private final BakedModel m_overlayModel; private final AffineTransformation m_generalTransform; private final TransformedModel m_leftUpgradeModel; private final TransformedModel m_rightUpgradeModel; private List m_generalQuads = null; - private Map> m_faceQuads = new EnumMap<>(Direction.class); + private Map> m_faceQuads = new EnumMap<>( Direction.class ); - public TurtleMultiModel(BakedModel baseModel, BakedModel overlayModel, AffineTransformation generalTransform, TransformedModel leftUpgradeModel, - TransformedModel rightUpgradeModel) { + public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, AffineTransformation generalTransform, TransformedModel leftUpgradeModel, + TransformedModel rightUpgradeModel ) + { // Get the models this.m_baseModel = baseModel; this.m_overlayModel = overlayModel; @@ -49,81 +44,98 @@ public class TurtleMultiModel implements BakedModel { @Nonnull @Override - public List getQuads(BlockState state, Direction side, @Nonnull Random rand) { - if (side != null) { - if (!this.m_faceQuads.containsKey(side)) { - this.m_faceQuads.put(side, this.buildQuads(state, side, rand)); + public List getQuads( BlockState state, Direction side, @Nonnull Random rand ) + { + if( side != null ) + { + if( !this.m_faceQuads.containsKey( side ) ) + { + this.m_faceQuads.put( side, this.buildQuads( state, side, rand ) ); } - return this.m_faceQuads.get(side); - } else { - if (this.m_generalQuads == null) { - this.m_generalQuads = this.buildQuads(state, side, rand); + return this.m_faceQuads.get( side ); + } + else + { + if( this.m_generalQuads == null ) + { + this.m_generalQuads = this.buildQuads( state, side, rand ); } return this.m_generalQuads; } } - private List buildQuads(BlockState state, Direction side, Random rand) { + private List buildQuads( BlockState state, Direction side, Random rand ) + { ArrayList quads = new ArrayList<>(); - ModelTransformer.transformQuadsTo(quads, this.m_baseModel.getQuads(state, side, rand), this.m_generalTransform.getMatrix()); - if (this.m_overlayModel != null) { - ModelTransformer.transformQuadsTo(quads, this.m_overlayModel.getQuads(state, side, rand), this.m_generalTransform.getMatrix()); + ModelTransformer.transformQuadsTo( quads, this.m_baseModel.getQuads( state, side, rand ), this.m_generalTransform.getMatrix() ); + if( this.m_overlayModel != null ) + { + ModelTransformer.transformQuadsTo( quads, this.m_overlayModel.getQuads( state, side, rand ), this.m_generalTransform.getMatrix() ); } - if (this.m_leftUpgradeModel != null) { - AffineTransformation upgradeTransform = this.m_generalTransform.multiply(this.m_leftUpgradeModel.getMatrix()); - ModelTransformer.transformQuadsTo(quads, this.m_leftUpgradeModel.getModel() - .getQuads(state, side, rand), - upgradeTransform.getMatrix()); + if( this.m_leftUpgradeModel != null ) + { + AffineTransformation upgradeTransform = this.m_generalTransform.multiply( this.m_leftUpgradeModel.getMatrix() ); + ModelTransformer.transformQuadsTo( quads, this.m_leftUpgradeModel.getModel() + .getQuads( state, side, rand ), + upgradeTransform.getMatrix() ); } - if (this.m_rightUpgradeModel != null) { - AffineTransformation upgradeTransform = this.m_generalTransform.multiply(this.m_rightUpgradeModel.getMatrix()); - ModelTransformer.transformQuadsTo(quads, this.m_rightUpgradeModel.getModel() - .getQuads(state, side, rand), - upgradeTransform.getMatrix()); + if( this.m_rightUpgradeModel != null ) + { + AffineTransformation upgradeTransform = this.m_generalTransform.multiply( this.m_rightUpgradeModel.getMatrix() ); + ModelTransformer.transformQuadsTo( quads, this.m_rightUpgradeModel.getModel() + .getQuads( state, side, rand ), + upgradeTransform.getMatrix() ); } quads.trimToSize(); return quads; } @Override - public boolean useAmbientOcclusion() { + public boolean useAmbientOcclusion() + { return this.m_baseModel.useAmbientOcclusion(); } @Override - public boolean hasDepth() { + public boolean hasDepth() + { return this.m_baseModel.hasDepth(); } @Override - public boolean isSideLit() { + public boolean isSideLit() + { return this.m_baseModel.isSideLit(); } @Override - public boolean isBuiltin() { + public boolean isBuiltin() + { return this.m_baseModel.isBuiltin(); } @Nonnull @Override @Deprecated - public Sprite getSprite() { + public Sprite getSprite() + { return this.m_baseModel.getSprite(); } @Nonnull @Override @Deprecated - public net.minecraft.client.render.model.json.ModelTransformation getTransformation() { + public net.minecraft.client.render.model.json.ModelTransformation getTransformation() + { return this.m_baseModel.getTransformation(); } @Nonnull @Override - public ModelOverrideList getOverrides() { + public ModelOverrideList getOverrides() + { return ModelOverrideList.EMPTY; } } diff --git a/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java b/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java index 186b12deb..636cc4b4d 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java @@ -5,35 +5,38 @@ */ package dan200.computercraft.client.render; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.turtle.core.TurtlePlayer; - +import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; -import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; +import javax.annotation.Nonnull; -public class TurtlePlayerRenderer extends EntityRenderer { - public TurtlePlayerRenderer(EntityRenderDispatcher renderManager) { - super(renderManager); +public class TurtlePlayerRenderer extends EntityRenderer +{ + public TurtlePlayerRenderer( EntityRenderDispatcher renderManager ) + { + super( renderManager ); } - public TurtlePlayerRenderer(EntityRenderDispatcher entityRenderDispatcher, EntityRendererRegistry.Context context) { - super(entityRenderDispatcher); + public TurtlePlayerRenderer( EntityRenderDispatcher entityRenderDispatcher, EntityRendererRegistry.Context context ) + { + super( entityRenderDispatcher ); } @Override - public void render(@Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull MatrixStack transform, - @Nonnull VertexConsumerProvider buffer, int packedLightIn) { + public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull MatrixStack transform, + @Nonnull VertexConsumerProvider buffer, int packedLightIn ) + { } @Nonnull @Override - public Identifier getTexture(@Nonnull TurtlePlayer entity) { + public Identifier getTexture( @Nonnull TurtlePlayer entity ) + { return ComputerBorderRenderer.BACKGROUND_NORMAL; } } diff --git a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java index 7465a5215..dcad3b2db 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java @@ -6,23 +6,15 @@ package dan200.computercraft.client.render; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Random; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.base.Objects; import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.turtle.items.ItemTurtle; -import dan200.computercraft.shared.turtle.upgrades.TurtleTool; import dan200.computercraft.shared.util.Holiday; import dan200.computercraft.shared.util.HolidayUtil; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.model.BakedModel; @@ -40,121 +32,142 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; import net.minecraft.util.math.Direction; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Random; -@Environment (EnvType.CLIENT) -public class TurtleSmartItemModel implements BakedModel { +@Environment( EnvType.CLIENT ) +public class TurtleSmartItemModel implements BakedModel +{ private static final AffineTransformation identity, flip; - static { + static + { MatrixStack stack = new MatrixStack(); - stack.scale(0, -1, 0); - stack.translate(0, 0, 1); + stack.scale( 0, -1, 0 ); + stack.translate( 0, 0, 1 ); identity = AffineTransformation.identity(); - flip = new AffineTransformation(stack.peek() - .getModel()); + flip = new AffineTransformation( stack.peek() + .getModel() ); } private final BakedModel familyModel; private final BakedModel colourModel; private final HashMap m_cachedModels = new HashMap<>(); private final ModelOverrideList m_overrides; - public TurtleSmartItemModel(BakedModel familyModel, BakedModel colourModel) { + + public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel ) + { this.familyModel = familyModel; this.colourModel = colourModel; // this actually works I think, trust me - this.m_overrides = new ModelOverrideList(null, null, null, Collections.emptyList()) { + this.m_overrides = new ModelOverrideList( null, null, null, Collections.emptyList() ) + { @Nonnull @Override - public BakedModel apply(@Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world, - @Nullable LivingEntity entity) { + public BakedModel apply( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world, + @Nullable LivingEntity entity ) + { ItemTurtle turtle = (ItemTurtle) stack.getItem(); - int colour = turtle.getColour(stack); - ITurtleUpgrade leftUpgrade = turtle.getUpgrade(stack, TurtleSide.LEFT); - ITurtleUpgrade rightUpgrade = turtle.getUpgrade(stack, TurtleSide.RIGHT); - Identifier overlay = turtle.getOverlay(stack); + int colour = turtle.getColour( stack ); + ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.LEFT ); + ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.RIGHT ); + Identifier overlay = turtle.getOverlay( stack ); boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS; - String label = turtle.getLabel(stack); + String label = turtle.getLabel( stack ); // TODO make upside down turtle items render properly (currently inivisible) //boolean flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm")); boolean flip = false; - TurtleModelCombination combo = new TurtleModelCombination(colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip); + TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip ); - BakedModel model = TurtleSmartItemModel.this.m_cachedModels.get(combo); - if (model == null) { - TurtleSmartItemModel.this.m_cachedModels.put(combo, model = TurtleSmartItemModel.this.buildModel(combo)); + BakedModel model = TurtleSmartItemModel.this.m_cachedModels.get( combo ); + if( model == null ) + { + TurtleSmartItemModel.this.m_cachedModels.put( combo, model = TurtleSmartItemModel.this.buildModel( combo ) ); } return model; } }; } - private BakedModel buildModel(TurtleModelCombination combo) { + private BakedModel buildModel( TurtleModelCombination combo ) + { MinecraftClient mc = MinecraftClient.getInstance(); BakedModelManager modelManager = mc.getItemRenderer() - .getModels() - .getModelManager(); - ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel(combo.m_overlay, combo.m_christmas); + .getModels() + .getModelManager(); + ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas ); BakedModel baseModel = combo.m_colour ? this.colourModel : this.familyModel; - BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel(overlayModelLocation) : null; + BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null; AffineTransformation transform = combo.m_flip ? flip : identity; - TransformedModel leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel(null, TurtleSide.LEFT) : null; - TransformedModel rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel(null, TurtleSide.RIGHT) : null; - return new TurtleMultiModel(baseModel, overlayModel, transform, leftModel, rightModel); + TransformedModel leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.LEFT ) : null; + TransformedModel rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null; + return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel, rightModel ); } @Nonnull @Override @Deprecated - public List getQuads(BlockState state, Direction facing, @Nonnull Random rand) { - return this.familyModel.getQuads(state, facing, rand); + public List getQuads( BlockState state, Direction facing, @Nonnull Random rand ) + { + return this.familyModel.getQuads( state, facing, rand ); } @Override - public boolean useAmbientOcclusion() { + public boolean useAmbientOcclusion() + { return this.familyModel.useAmbientOcclusion(); } @Override - public boolean hasDepth() { + public boolean hasDepth() + { return this.familyModel.hasDepth(); } @Override - public boolean isSideLit() { + public boolean isSideLit() + { return this.familyModel.isSideLit(); } @Override - public boolean isBuiltin() { + public boolean isBuiltin() + { return this.familyModel.isBuiltin(); } @Nonnull @Override @Deprecated - public Sprite getSprite() { + public Sprite getSprite() + { return this.familyModel.getSprite(); } @Nonnull @Override @Deprecated - public ModelTransformation getTransformation() { + public ModelTransformation getTransformation() + { return this.familyModel.getTransformation(); } @Nonnull @Override - public ModelOverrideList getOverrides() { + public ModelOverrideList getOverrides() + { return this.m_overrides; } - private static class TurtleModelCombination { + private static class TurtleModelCombination + { final boolean m_colour; final ITurtleUpgrade m_leftUpgrade; final ITurtleUpgrade m_rightUpgrade; @@ -162,8 +175,9 @@ public class TurtleSmartItemModel implements BakedModel { final boolean m_christmas; final boolean m_flip; - TurtleModelCombination(boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas, - boolean flip) { + TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas, + boolean flip ) + { this.m_colour = colour; this.m_leftUpgrade = leftUpgrade; this.m_rightUpgrade = rightUpgrade; @@ -173,7 +187,8 @@ public class TurtleSmartItemModel implements BakedModel { } @Override - public int hashCode() { + public int hashCode() + { final int prime = 31; int result = 0; result = prime * result + (this.m_colour ? 1 : 0); @@ -186,17 +201,20 @@ public class TurtleSmartItemModel implements BakedModel { } @Override - public boolean equals(Object other) { - if (other == this) { + public boolean equals( Object other ) + { + if( other == this ) + { return true; } - if (!(other instanceof TurtleModelCombination)) { + if( !(other instanceof TurtleModelCombination) ) + { return false; } TurtleModelCombination otherCombo = (TurtleModelCombination) other; return otherCombo.m_colour == this.m_colour && otherCombo.m_leftUpgrade == this.m_leftUpgrade && otherCombo.m_rightUpgrade == this.m_rightUpgrade && Objects.equal( - otherCombo.m_overlay, this.m_overlay) && otherCombo.m_christmas == this.m_christmas && otherCombo.m_flip == this.m_flip; + otherCombo.m_overlay, this.m_overlay ) && otherCombo.m_christmas == this.m_christmas && otherCombo.m_flip == this.m_flip; } } diff --git a/src/main/java/dan200/computercraft/core/apis/ApiFactories.java b/src/main/java/dan200/computercraft/core/apis/ApiFactories.java index 4a370d49f..fc4b9eff7 100644 --- a/src/main/java/dan200/computercraft/core/apis/ApiFactories.java +++ b/src/main/java/dan200/computercraft/core/apis/ApiFactories.java @@ -6,27 +6,31 @@ package dan200.computercraft.core.apis; +import dan200.computercraft.api.lua.ILuaAPIFactory; + +import javax.annotation.Nonnull; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Objects; -import javax.annotation.Nonnull; - -import dan200.computercraft.api.lua.ILuaAPIFactory; - -public final class ApiFactories { +public final class ApiFactories +{ private static final Collection factories = new LinkedHashSet<>(); - private static final Collection factoriesView = Collections.unmodifiableCollection(factories); - private ApiFactories() { + private static final Collection factoriesView = Collections.unmodifiableCollection( factories ); + + private ApiFactories() + { } - public static synchronized void register(@Nonnull ILuaAPIFactory factory) { - Objects.requireNonNull(factory, "provider cannot be null"); - factories.add(factory); + public static synchronized void register( @Nonnull ILuaAPIFactory factory ) + { + Objects.requireNonNull( factory, "provider cannot be null" ); + factories.add( factory ); } - public static Iterable getAll() { + public static Iterable getAll() + { return factoriesView; } } diff --git a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java index 27c5e504b..c71e9ec7b 100644 --- a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java +++ b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java @@ -6,12 +6,6 @@ package dan200.computercraft.core.apis; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.peripheral.IComputerAccess; @@ -19,121 +13,157 @@ import dan200.computercraft.api.peripheral.IWorkMonitor; import dan200.computercraft.core.filesystem.FileSystem; import dan200.computercraft.core.filesystem.FileSystemException; -public abstract class ComputerAccess implements IComputerAccess { +import javax.annotation.Nonnull; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public abstract class ComputerAccess implements IComputerAccess +{ private final IAPIEnvironment m_environment; private final Set m_mounts = new HashSet<>(); - protected ComputerAccess(IAPIEnvironment environment) { + protected ComputerAccess( IAPIEnvironment environment ) + { this.m_environment = environment; } - public void unmountAll() { + public void unmountAll() + { FileSystem fileSystem = this.m_environment.getFileSystem(); - for (String mount : this.m_mounts) { - fileSystem.unmount(mount); + for( String mount : this.m_mounts ) + { + fileSystem.unmount( mount ); } this.m_mounts.clear(); } @Override - public synchronized String mount(@Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName) { - Objects.requireNonNull(desiredLoc, "desiredLocation cannot be null"); - Objects.requireNonNull(mount, "mount cannot be null"); - Objects.requireNonNull(driveName, "driveName cannot be null"); + public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName ) + { + Objects.requireNonNull( desiredLoc, "desiredLocation cannot be null" ); + Objects.requireNonNull( mount, "mount cannot be null" ); + Objects.requireNonNull( driveName, "driveName cannot be null" ); // Mount the location String location; FileSystem fileSystem = this.m_environment.getFileSystem(); - if (fileSystem == null) { - throw new IllegalStateException("File system has not been created"); + if( fileSystem == null ) + { + throw new IllegalStateException( "File system has not been created" ); } - synchronized (fileSystem) { - location = this.findFreeLocation(desiredLoc); - if (location != null) { - try { - fileSystem.mount(driveName, location, mount); - } catch (FileSystemException ignored) { + synchronized( fileSystem ) + { + location = this.findFreeLocation( desiredLoc ); + if( location != null ) + { + try + { + fileSystem.mount( driveName, location, mount ); + } + catch( FileSystemException ignored ) + { } } } - if (location != null) { - this.m_mounts.add(location); + if( location != null ) + { + this.m_mounts.add( location ); } return location; } @Override - public synchronized String mountWritable(@Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName) { - Objects.requireNonNull(desiredLoc, "desiredLocation cannot be null"); - Objects.requireNonNull(mount, "mount cannot be null"); - Objects.requireNonNull(driveName, "driveName cannot be null"); + public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName ) + { + Objects.requireNonNull( desiredLoc, "desiredLocation cannot be null" ); + Objects.requireNonNull( mount, "mount cannot be null" ); + Objects.requireNonNull( driveName, "driveName cannot be null" ); // Mount the location String location; FileSystem fileSystem = this.m_environment.getFileSystem(); - if (fileSystem == null) { - throw new IllegalStateException("File system has not been created"); + if( fileSystem == null ) + { + throw new IllegalStateException( "File system has not been created" ); } - synchronized (fileSystem) { - location = this.findFreeLocation(desiredLoc); - if (location != null) { - try { - fileSystem.mountWritable(driveName, location, mount); - } catch (FileSystemException ignored) { + synchronized( fileSystem ) + { + location = this.findFreeLocation( desiredLoc ); + if( location != null ) + { + try + { + fileSystem.mountWritable( driveName, location, mount ); + } + catch( FileSystemException ignored ) + { } } } - if (location != null) { - this.m_mounts.add(location); + if( location != null ) + { + this.m_mounts.add( location ); } return location; } @Override - public void unmount(String location) { - if (location == null) { + public void unmount( String location ) + { + if( location == null ) + { return; } - if (!this.m_mounts.contains(location)) { - throw new IllegalStateException("You didn't mount this location"); + if( !this.m_mounts.contains( location ) ) + { + throw new IllegalStateException( "You didn't mount this location" ); } this.m_environment.getFileSystem() - .unmount(location); - this.m_mounts.remove(location); + .unmount( location ); + this.m_mounts.remove( location ); } @Override - public int getID() { + public int getID() + { return this.m_environment.getComputerID(); } @Override - public void queueEvent(@Nonnull String event, Object... arguments) { - Objects.requireNonNull(event, "event cannot be null"); - this.m_environment.queueEvent(event, arguments); + public void queueEvent( @Nonnull String event, Object... arguments ) + { + Objects.requireNonNull( event, "event cannot be null" ); + this.m_environment.queueEvent( event, arguments ); } @Nonnull @Override - public IWorkMonitor getMainThreadMonitor() { + public IWorkMonitor getMainThreadMonitor() + { return this.m_environment.getMainThreadMonitor(); } - private String findFreeLocation(String desiredLoc) { - try { + private String findFreeLocation( String desiredLoc ) + { + try + { FileSystem fileSystem = this.m_environment.getFileSystem(); - if (!fileSystem.exists(desiredLoc)) { + if( !fileSystem.exists( desiredLoc ) ) + { return desiredLoc; } // We used to check foo2, foo3, foo4, etc here but the disk drive does this itself now return null; - } catch (FileSystemException e) { + } + catch( FileSystemException e ) + { return null; } } diff --git a/src/main/java/dan200/computercraft/core/apis/FSAPI.java b/src/main/java/dan200/computercraft/core/apis/FSAPI.java index c2156a069..fa174c003 100644 --- a/src/main/java/dan200/computercraft/core/apis/FSAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/FSAPI.java @@ -6,18 +6,6 @@ package dan200.computercraft.core.apis; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; -import java.util.HashMap; -import java.util.Map; -import java.util.OptionalLong; -import java.util.function.Function; - - import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.ILuaAPI; import dan200.computercraft.api.lua.LuaException; @@ -31,31 +19,47 @@ import dan200.computercraft.core.filesystem.FileSystemException; import dan200.computercraft.core.filesystem.FileSystemWrapper; import dan200.computercraft.core.tracking.TrackingField; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.util.HashMap; +import java.util.Map; +import java.util.OptionalLong; +import java.util.function.Function; + /** * The FS API allows you to manipulate files and the filesystem. * * @cc.module fs */ -public class FSAPI implements ILuaAPI { +public class FSAPI implements ILuaAPI +{ private final IAPIEnvironment environment; private FileSystem fileSystem = null; - public FSAPI(IAPIEnvironment env) { + public FSAPI( IAPIEnvironment env ) + { this.environment = env; } @Override - public String[] getNames() { - return new String[] {"fs"}; + public String[] getNames() + { + return new String[] { "fs" }; } @Override - public void startup() { + public void startup() + { this.fileSystem = this.environment.getFileSystem(); } @Override - public void shutdown() { + public void shutdown() + { this.fileSystem = null; } @@ -67,12 +71,16 @@ public class FSAPI implements ILuaAPI { * @throws LuaException If the path doesn't exist. */ @LuaFunction - public final String[] list(String path) throws LuaException { - this.environment.addTrackingChange(TrackingField.FS_OPS); - try { - return this.fileSystem.list(path); - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final String[] list( String path ) throws LuaException + { + this.environment.addTrackingChange( TrackingField.FS_OPS ); + try + { + return this.fileSystem.list( path ); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -82,22 +90,24 @@ public class FSAPI implements ILuaAPI { * * @param arguments The paths to combine. * @return The new path, with separators added between parts as needed. + * @throws LuaException On argument errors. * @cc.tparam string path The first part of the path. For example, a parent directory path. * @cc.tparam string ... Additional parts of the path to combine. - * @throws LuaException On argument errors. */ @LuaFunction - public final String combine( IArguments arguments ) throws LuaException { + public final String combine( IArguments arguments ) throws LuaException + { StringBuilder result = new StringBuilder(); - result.append(FileSystem.sanitizePath(arguments.getString(0), true)); + result.append( FileSystem.sanitizePath( arguments.getString( 0 ), true ) ); - for (int i = 1, n = arguments.count(); i < n; i++) { - String part = FileSystem.sanitizePath(arguments.getString(i), true); - if (result.length() != 0 && !part.isEmpty()) result.append('/'); - result.append(part); + for( int i = 1, n = arguments.count(); i < n; i++ ) + { + String part = FileSystem.sanitizePath( arguments.getString( i ), true ); + if( result.length() != 0 && !part.isEmpty() ) result.append( '/' ); + result.append( part ); } - return FileSystem.sanitizePath(result.toString(), true); + return FileSystem.sanitizePath( result.toString(), true ); } /** @@ -107,8 +117,9 @@ public class FSAPI implements ILuaAPI { * @return The final part of the path (the file name). */ @LuaFunction - public final String getName(String path) { - return FileSystem.getName(path); + public final String getName( String path ) + { + return FileSystem.getName( path ); } /** @@ -118,8 +129,9 @@ public class FSAPI implements ILuaAPI { * @return The path with the final part removed (the parent directory). */ @LuaFunction - public final String getDir(String path) { - return FileSystem.getDirectory(path); + public final String getDir( String path ) + { + return FileSystem.getDirectory( path ); } /** @@ -130,11 +142,15 @@ public class FSAPI implements ILuaAPI { * @throws LuaException If the path doesn't exist. */ @LuaFunction - public final long getSize(String path) throws LuaException { - try { - return this.fileSystem.getSize(path); - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final long getSize( String path ) throws LuaException + { + try + { + return this.fileSystem.getSize( path ); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -145,10 +161,14 @@ public class FSAPI implements ILuaAPI { * @return Whether the path exists. */ @LuaFunction - public final boolean exists(String path) { - try { - return this.fileSystem.exists(path); - } catch (FileSystemException e) { + public final boolean exists( String path ) + { + try + { + return this.fileSystem.exists( path ); + } + catch( FileSystemException e ) + { return false; } } @@ -160,10 +180,14 @@ public class FSAPI implements ILuaAPI { * @return Whether the path is a directory. */ @LuaFunction - public final boolean isDir(String path) { - try { - return this.fileSystem.isDir(path); - } catch (FileSystemException e) { + public final boolean isDir( String path ) + { + try + { + return this.fileSystem.isDir( path ); + } + catch( FileSystemException e ) + { return false; } } @@ -175,10 +199,14 @@ public class FSAPI implements ILuaAPI { * @return Whether the path cannot be written to. */ @LuaFunction - public final boolean isReadOnly(String path) { - try { - return this.fileSystem.isReadOnly(path); - } catch (FileSystemException e) { + public final boolean isReadOnly( String path ) + { + try + { + return this.fileSystem.isReadOnly( path ); + } + catch( FileSystemException e ) + { return false; } } @@ -190,12 +218,16 @@ public class FSAPI implements ILuaAPI { * @throws LuaException If the directory couldn't be created. */ @LuaFunction - public final void makeDir(String path) throws LuaException { - try { - this.environment.addTrackingChange(TrackingField.FS_OPS); - this.fileSystem.makeDir(path); - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final void makeDir( String path ) throws LuaException + { + try + { + this.environment.addTrackingChange( TrackingField.FS_OPS ); + this.fileSystem.makeDir( path ); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -209,12 +241,16 @@ public class FSAPI implements ILuaAPI { * @throws LuaException If the file or directory couldn't be moved. */ @LuaFunction - public final void move(String path, String dest) throws LuaException { - try { - this.environment.addTrackingChange(TrackingField.FS_OPS); - this.fileSystem.move(path, dest); - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final void move( String path, String dest ) throws LuaException + { + try + { + this.environment.addTrackingChange( TrackingField.FS_OPS ); + this.fileSystem.move( path, dest ); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -228,12 +264,16 @@ public class FSAPI implements ILuaAPI { * @throws LuaException If the file or directory couldn't be copied. */ @LuaFunction - public final void copy(String path, String dest) throws LuaException { - try { - this.environment.addTrackingChange(TrackingField.FS_OPS); - this.fileSystem.copy(path, dest); - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final void copy( String path, String dest ) throws LuaException + { + try + { + this.environment.addTrackingChange( TrackingField.FS_OPS ); + this.fileSystem.copy( path, dest ); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -246,12 +286,16 @@ public class FSAPI implements ILuaAPI { * @throws LuaException If the file or directory couldn't be deleted. */ @LuaFunction - public final void delete(String path) throws LuaException { - try { - this.environment.addTrackingChange(TrackingField.FS_OPS); - this.fileSystem.delete(path); - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final void delete( String path ) throws LuaException + { + try + { + this.environment.addTrackingChange( TrackingField.FS_OPS ); + this.fileSystem.delete( path ); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -272,44 +316,55 @@ public class FSAPI implements ILuaAPI { * @cc.treturn string|nil A message explaining why the file cannot be opened. */ @LuaFunction - public final Object[] open(String path, String mode) throws LuaException { - this.environment.addTrackingChange(TrackingField.FS_OPS); - try { - switch (mode) { - case "r": { - // Open the file for reading, then create a wrapper around the reader - FileSystemWrapper reader = this.fileSystem.openForRead(path, EncodedReadableHandle::openUtf8); - return new Object[] {new EncodedReadableHandle(reader.get(), reader)}; + public final Object[] open( String path, String mode ) throws LuaException + { + this.environment.addTrackingChange( TrackingField.FS_OPS ); + try + { + switch( mode ) + { + case "r": + { + // Open the file for reading, then create a wrapper around the reader + FileSystemWrapper reader = this.fileSystem.openForRead( path, EncodedReadableHandle::openUtf8 ); + return new Object[] { new EncodedReadableHandle( reader.get(), reader ) }; + } + case "w": + { + // Open the file for writing, then create a wrapper around the writer + FileSystemWrapper writer = this.fileSystem.openForWrite( path, false, EncodedWritableHandle::openUtf8 ); + return new Object[] { new EncodedWritableHandle( writer.get(), writer ) }; + } + case "a": + { + // Open the file for appending, then create a wrapper around the writer + FileSystemWrapper writer = this.fileSystem.openForWrite( path, true, EncodedWritableHandle::openUtf8 ); + return new Object[] { new EncodedWritableHandle( writer.get(), writer ) }; + } + case "rb": + { + // Open the file for binary reading, then create a wrapper around the reader + FileSystemWrapper reader = this.fileSystem.openForRead( path, Function.identity() ); + return new Object[] { BinaryReadableHandle.of( reader.get(), reader ) }; + } + case "wb": + { + // Open the file for binary writing, then create a wrapper around the writer + FileSystemWrapper writer = this.fileSystem.openForWrite( path, false, Function.identity() ); + return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) }; + } + case "ab": + { + // Open the file for binary appending, then create a wrapper around the reader + FileSystemWrapper writer = this.fileSystem.openForWrite( path, true, Function.identity() ); + return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) }; + } + default: + throw new LuaException( "Unsupported mode" ); } - case "w": { - // Open the file for writing, then create a wrapper around the writer - FileSystemWrapper writer = this.fileSystem.openForWrite(path, false, EncodedWritableHandle::openUtf8); - return new Object[] {new EncodedWritableHandle(writer.get(), writer)}; - } - case "a": { - // Open the file for appending, then create a wrapper around the writer - FileSystemWrapper writer = this.fileSystem.openForWrite(path, true, EncodedWritableHandle::openUtf8); - return new Object[] {new EncodedWritableHandle(writer.get(), writer)}; - } - case "rb": { - // Open the file for binary reading, then create a wrapper around the reader - FileSystemWrapper reader = this.fileSystem.openForRead(path, Function.identity()); - return new Object[] {BinaryReadableHandle.of(reader.get(), reader)}; - } - case "wb": { - // Open the file for binary writing, then create a wrapper around the writer - FileSystemWrapper writer = this.fileSystem.openForWrite(path, false, Function.identity()); - return new Object[] {BinaryWritableHandle.of(writer.get(), writer)}; - } - case "ab": { - // Open the file for binary appending, then create a wrapper around the reader - FileSystemWrapper writer = this.fileSystem.openForWrite(path, true, Function.identity()); - return new Object[] {BinaryWritableHandle.of(writer.get(), writer)}; - } - default: - throw new LuaException("Unsupported mode"); - } - } catch (FileSystemException e) { + } + catch( FileSystemException e ) + { return new Object[] { null, e.getMessage() @@ -326,11 +381,15 @@ public class FSAPI implements ILuaAPI { * @cc.treturn string The name of the drive that the file is on; e.g. {@code hdd} for local files, or {@code rom} for ROM files. */ @LuaFunction - public final Object[] getDrive(String path) throws LuaException { - try { - return this.fileSystem.exists(path) ? new Object[] {this.fileSystem.getMountLabel(path)} : null; - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final Object[] getDrive( String path ) throws LuaException + { + try + { + return this.fileSystem.exists( path ) ? new Object[] { this.fileSystem.getMountLabel( path ) } : null; + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -343,12 +402,16 @@ public class FSAPI implements ILuaAPI { * @cc.treturn number|"unlimited" The amount of free space available, in bytes, or "unlimited". */ @LuaFunction - public final Object getFreeSpace(String path) throws LuaException { - try { - long freeSpace = this.fileSystem.getFreeSpace(path); + public final Object getFreeSpace( String path ) throws LuaException + { + try + { + long freeSpace = this.fileSystem.getFreeSpace( path ); return freeSpace >= 0 ? freeSpace : "unlimited"; - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -363,12 +426,16 @@ public class FSAPI implements ILuaAPI { * @throws LuaException If the path doesn't exist. */ @LuaFunction - public final String[] find(String path) throws LuaException { - try { - this.environment.addTrackingChange(TrackingField.FS_OPS); - return this.fileSystem.find(path); - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + public final String[] find( String path ) throws LuaException + { + try + { + this.environment.addTrackingChange( TrackingField.FS_OPS ); + return this.fileSystem.find( path ); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -384,12 +451,16 @@ public class FSAPI implements ILuaAPI { * @cc.treturn number|nil This drive's capacity. This will be nil for "read-only" drives, such as the ROM or treasure disks. */ @LuaFunction - public final Object getCapacity(String path) throws LuaException { - try { - OptionalLong capacity = this.fileSystem.getCapacity(path); + public final Object getCapacity( String path ) throws LuaException + { + try + { + OptionalLong capacity = this.fileSystem.getCapacity( path ); return capacity.isPresent() ? capacity.getAsLong() : null; - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } @@ -410,9 +481,11 @@ public class FSAPI implements ILuaAPI { * @see #isDir If you only care whether a path is a directory or not. */ @LuaFunction - public final Map attributes(String path) throws LuaException { - try { - BasicFileAttributes attributes = this.fileSystem.getAttributes(path); + public final Map attributes( String path ) throws LuaException + { + try + { + BasicFileAttributes attributes = this.fileSystem.getAttributes( path ); Map result = new HashMap<>(); result.put( "modification", getFileTime( attributes.lastModifiedTime() ) ); result.put( "modified", getFileTime( attributes.lastModifiedTime() ) ); @@ -421,12 +494,15 @@ public class FSAPI implements ILuaAPI { result.put( "isDir", attributes.isDirectory() ); result.put( "isReadOnly", fileSystem.isReadOnly( path ) ); return result; - } catch (FileSystemException e) { - throw new LuaException(e.getMessage()); + } + catch( FileSystemException e ) + { + throw new LuaException( e.getMessage() ); } } - private static long getFileTime(FileTime time) { + private static long getFileTime( FileTime time ) + { return time == null ? 0 : time.toMillis(); } } diff --git a/src/main/java/dan200/computercraft/core/apis/FastLuaException.java b/src/main/java/dan200/computercraft/core/apis/FastLuaException.java index cee6aead1..45e4db0b2 100644 --- a/src/main/java/dan200/computercraft/core/apis/FastLuaException.java +++ b/src/main/java/dan200/computercraft/core/apis/FastLuaException.java @@ -5,26 +5,30 @@ */ package dan200.computercraft.core.apis; -import javax.annotation.Nullable; - import dan200.computercraft.api.lua.LuaException; +import javax.annotation.Nullable; + /** * A Lua exception which does not contain its stack trace. */ -public class FastLuaException extends LuaException { +public class FastLuaException extends LuaException +{ private static final long serialVersionUID = 5957864899303561143L; - public FastLuaException(@Nullable String message) { - super(message); + public FastLuaException( @Nullable String message ) + { + super( message ); } - public FastLuaException(@Nullable String message, int level) { - super(message, level); + public FastLuaException( @Nullable String message, int level ) + { + super( message, level ); } @Override - public synchronized Throwable fillInStackTrace() { + public synchronized Throwable fillInStackTrace() + { return this; } } diff --git a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java index 698f783b4..396232e92 100644 --- a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java @@ -156,7 +156,7 @@ public class HTTPAPI implements ILuaAPI @LuaFunction public final Object[] websocket( String address, Optional> headerTbl ) throws LuaException { - if( !ComputerCraft.httpWebsocketEnabled) + if( !ComputerCraft.httpWebsocketEnabled ) { throw new LuaException( "Websocket connections are disabled" ); } @@ -205,4 +205,4 @@ public class HTTPAPI implements ILuaAPI } return headers; } -} \ No newline at end of file +} diff --git a/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java index ef130fae0..8376b598d 100644 --- a/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java +++ b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java @@ -6,9 +6,6 @@ package dan200.computercraft.core.apis; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IWorkMonitor; import dan200.computercraft.core.computer.ComputerSide; @@ -17,7 +14,11 @@ import dan200.computercraft.core.filesystem.FileSystem; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.tracking.TrackingField; -public interface IAPIEnvironment { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface IAPIEnvironment +{ String TIMER_EVENT = "timer"; int getComputerID(); @@ -37,41 +38,43 @@ public interface IAPIEnvironment { void reboot(); - void queueEvent(String event, Object... args); + void queueEvent( String event, Object... args ); - void setOutput(ComputerSide side, int output); + void setOutput( ComputerSide side, int output ); - int getOutput(ComputerSide side); + int getOutput( ComputerSide side ); - int getInput(ComputerSide side); + int getInput( ComputerSide side ); - void setBundledOutput(ComputerSide side, int output); + void setBundledOutput( ComputerSide side, int output ); - int getBundledOutput(ComputerSide side); + int getBundledOutput( ComputerSide side ); - int getBundledInput(ComputerSide side); + int getBundledInput( ComputerSide side ); - void setPeripheralChangeListener(@Nullable IPeripheralChangeListener listener); + void setPeripheralChangeListener( @Nullable IPeripheralChangeListener listener ); @Nullable - IPeripheral getPeripheral(ComputerSide side); + IPeripheral getPeripheral( ComputerSide side ); String getLabel(); - void setLabel(@Nullable String label); + void setLabel( @Nullable String label ); - int startTimer(long ticks); + int startTimer( long ticks ); - void cancelTimer(int id); + void cancelTimer( int id ); - default void addTrackingChange(@Nonnull TrackingField field) { - this.addTrackingChange(field, 1); + default void addTrackingChange( @Nonnull TrackingField field ) + { + this.addTrackingChange( field, 1 ); } - void addTrackingChange(@Nonnull TrackingField field, long change); + void addTrackingChange( @Nonnull TrackingField field, long change ); @FunctionalInterface - interface IPeripheralChangeListener { - void onPeripheralChanged(ComputerSide side, @Nullable IPeripheral newPeripheral); + interface IPeripheralChangeListener + { + void onPeripheralChanged( ComputerSide side, @Nullable IPeripheral newPeripheral ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java b/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java index 39f307a20..fbb486296 100644 --- a/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java +++ b/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java @@ -6,276 +6,297 @@ package dan200.computercraft.core.apis; +import dan200.computercraft.api.lua.LuaException; + import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.format.DateTimeFormatterBuilder; import java.time.format.TextStyle; -import java.time.temporal.ChronoField; -import java.time.temporal.IsoFields; -import java.time.temporal.Temporal; -import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalField; -import java.time.temporal.TemporalUnit; -import java.time.temporal.ValueRange; -import java.time.temporal.WeekFields; +import java.time.temporal.*; import java.util.HashMap; import java.util.Map; import java.util.function.LongUnaryOperator; -import dan200.computercraft.api.lua.LuaException; +final class LuaDateTime +{ + private static final TemporalField CENTURY = map( ChronoField.YEAR, ValueRange.of( 0, 6 ), x -> (x / 100) % 100 ); + private static final TemporalField ZERO_WEEK = map( WeekFields.SUNDAY_START.dayOfWeek(), ValueRange.of( 0, 6 ), x -> x - 1 ); -final class LuaDateTime { - private static final TemporalField CENTURY = map(ChronoField.YEAR, ValueRange.of(0, 6), x -> (x / 100) % 100); - private static final TemporalField ZERO_WEEK = map(WeekFields.SUNDAY_START.dayOfWeek(), ValueRange.of(0, 6), x -> x - 1); - - private LuaDateTime() { + private LuaDateTime() + { } - static void format(DateTimeFormatterBuilder formatter, String format, ZoneOffset offset) throws LuaException { - for (int i = 0; i < format.length(); ) { + static void format( DateTimeFormatterBuilder formatter, String format, ZoneOffset offset ) throws LuaException + { + for( int i = 0; i < format.length(); ) + { char c; - switch (c = format.charAt(i++)) { - case '\n': - formatter.appendLiteral('\n'); - break; - default: - formatter.appendLiteral(c); - break; - case '%': - if (i >= format.length()) { + switch( c = format.charAt( i++ ) ) + { + case '\n': + formatter.appendLiteral( '\n' ); break; - } - switch (c = format.charAt(i++)) { default: - throw new LuaException("bad argument #1: invalid conversion specifier '%" + c + "'"); - + formatter.appendLiteral( c ); + break; case '%': - formatter.appendLiteral('%'); - break; - case 'a': - formatter.appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT); - break; - case 'A': - formatter.appendText(ChronoField.DAY_OF_WEEK, TextStyle.FULL); - break; - case 'b': - case 'h': - formatter.appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT); - break; - case 'B': - formatter.appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL); - break; - case 'c': - format(formatter, "%a %b %e %H:%M:%S %Y", offset); - break; - case 'C': - formatter.appendValueReduced(CENTURY, 2, 2, 0); - break; - case 'd': - formatter.appendValue(ChronoField.DAY_OF_MONTH, 2); - break; - case 'D': - case 'x': - format(formatter, "%m/%d/%y", offset); - break; - case 'e': - formatter.padNext(2) - .appendValue(ChronoField.DAY_OF_MONTH); - break; - case 'F': - format(formatter, "%Y-%m-%d", offset); - break; - case 'g': - formatter.appendValueReduced(IsoFields.WEEK_BASED_YEAR, 2, 2, 0); - break; - case 'G': - formatter.appendValue(IsoFields.WEEK_BASED_YEAR); - break; - case 'H': - formatter.appendValue(ChronoField.HOUR_OF_DAY, 2); - break; - case 'I': - formatter.appendValue(ChronoField.HOUR_OF_AMPM); - break; - case 'j': - formatter.appendValue(ChronoField.DAY_OF_YEAR, 3); - break; - case 'm': - formatter.appendValue(ChronoField.MONTH_OF_YEAR, 2); - break; - case 'M': - formatter.appendValue(ChronoField.MINUTE_OF_HOUR, 2); - break; - case 'n': - formatter.appendLiteral('\n'); - break; - case 'p': - formatter.appendText(ChronoField.AMPM_OF_DAY); - break; - case 'r': - format(formatter, "%I:%M:%S %p", offset); - break; - case 'R': - format(formatter, "%H:%M", offset); - break; - case 'S': - formatter.appendValue(ChronoField.SECOND_OF_MINUTE, 2); - break; - case 't': - formatter.appendLiteral('\t'); - break; - case 'T': - case 'X': - format(formatter, "%H:%M:%S", offset); - break; - case 'u': - formatter.appendValue(ChronoField.DAY_OF_WEEK); - break; - case 'U': - formatter.appendValue(ChronoField.ALIGNED_WEEK_OF_YEAR, 2); - break; - case 'V': - formatter.appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2); - break; - case 'w': - formatter.appendValue(ZERO_WEEK); - break; - case 'W': - formatter.appendValue(WeekFields.ISO.weekOfYear(), 2); - break; - case 'y': - formatter.appendValueReduced(ChronoField.YEAR, 2, 2, 0); - break; - case 'Y': - formatter.appendValue(ChronoField.YEAR); - break; - case 'z': - formatter.appendOffset("+HHMM", "+0000"); - break; - case 'Z': - formatter.appendChronologyId(); - break; - } + if( i >= format.length() ) + { + break; + } + switch( c = format.charAt( i++ ) ) + { + default: + throw new LuaException( "bad argument #1: invalid conversion specifier '%" + c + "'" ); + + case '%': + formatter.appendLiteral( '%' ); + break; + case 'a': + formatter.appendText( ChronoField.DAY_OF_WEEK, TextStyle.SHORT ); + break; + case 'A': + formatter.appendText( ChronoField.DAY_OF_WEEK, TextStyle.FULL ); + break; + case 'b': + case 'h': + formatter.appendText( ChronoField.MONTH_OF_YEAR, TextStyle.SHORT ); + break; + case 'B': + formatter.appendText( ChronoField.MONTH_OF_YEAR, TextStyle.FULL ); + break; + case 'c': + format( formatter, "%a %b %e %H:%M:%S %Y", offset ); + break; + case 'C': + formatter.appendValueReduced( CENTURY, 2, 2, 0 ); + break; + case 'd': + formatter.appendValue( ChronoField.DAY_OF_MONTH, 2 ); + break; + case 'D': + case 'x': + format( formatter, "%m/%d/%y", offset ); + break; + case 'e': + formatter.padNext( 2 ) + .appendValue( ChronoField.DAY_OF_MONTH ); + break; + case 'F': + format( formatter, "%Y-%m-%d", offset ); + break; + case 'g': + formatter.appendValueReduced( IsoFields.WEEK_BASED_YEAR, 2, 2, 0 ); + break; + case 'G': + formatter.appendValue( IsoFields.WEEK_BASED_YEAR ); + break; + case 'H': + formatter.appendValue( ChronoField.HOUR_OF_DAY, 2 ); + break; + case 'I': + formatter.appendValue( ChronoField.HOUR_OF_AMPM ); + break; + case 'j': + formatter.appendValue( ChronoField.DAY_OF_YEAR, 3 ); + break; + case 'm': + formatter.appendValue( ChronoField.MONTH_OF_YEAR, 2 ); + break; + case 'M': + formatter.appendValue( ChronoField.MINUTE_OF_HOUR, 2 ); + break; + case 'n': + formatter.appendLiteral( '\n' ); + break; + case 'p': + formatter.appendText( ChronoField.AMPM_OF_DAY ); + break; + case 'r': + format( formatter, "%I:%M:%S %p", offset ); + break; + case 'R': + format( formatter, "%H:%M", offset ); + break; + case 'S': + formatter.appendValue( ChronoField.SECOND_OF_MINUTE, 2 ); + break; + case 't': + formatter.appendLiteral( '\t' ); + break; + case 'T': + case 'X': + format( formatter, "%H:%M:%S", offset ); + break; + case 'u': + formatter.appendValue( ChronoField.DAY_OF_WEEK ); + break; + case 'U': + formatter.appendValue( ChronoField.ALIGNED_WEEK_OF_YEAR, 2 ); + break; + case 'V': + formatter.appendValue( IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2 ); + break; + case 'w': + formatter.appendValue( ZERO_WEEK ); + break; + case 'W': + formatter.appendValue( WeekFields.ISO.weekOfYear(), 2 ); + break; + case 'y': + formatter.appendValueReduced( ChronoField.YEAR, 2, 2, 0 ); + break; + case 'Y': + formatter.appendValue( ChronoField.YEAR ); + break; + case 'z': + formatter.appendOffset( "+HHMM", "+0000" ); + break; + case 'Z': + formatter.appendChronologyId(); + break; + } } } } - static long fromTable(Map table) throws LuaException { - int year = getField(table, "year", -1); - int month = getField(table, "month", -1); - int day = getField(table, "day", -1); - int hour = getField(table, "hour", 12); - int minute = getField(table, "min", 12); - int second = getField(table, "sec", 12); - LocalDateTime time = LocalDateTime.of(year, month, day, hour, minute, second); + static long fromTable( Map table ) throws LuaException + { + int year = getField( table, "year", -1 ); + int month = getField( table, "month", -1 ); + int day = getField( table, "day", -1 ); + int hour = getField( table, "hour", 12 ); + int minute = getField( table, "min", 12 ); + int second = getField( table, "sec", 12 ); + LocalDateTime time = LocalDateTime.of( year, month, day, hour, minute, second ); - Boolean isDst = getBoolField(table, "isdst"); - if (isDst != null) { + Boolean isDst = getBoolField( table, "isdst" ); + if( isDst != null ) + { boolean requireDst = isDst; - for (ZoneOffset possibleOffset : ZoneOffset.systemDefault() - .getRules() - .getValidOffsets(time)) { - Instant instant = time.toInstant(possibleOffset); - if (possibleOffset.getRules() - .getDaylightSavings(instant) - .isZero() == requireDst) { + for( ZoneOffset possibleOffset : ZoneOffset.systemDefault() + .getRules() + .getValidOffsets( time ) ) + { + Instant instant = time.toInstant( possibleOffset ); + if( possibleOffset.getRules() + .getDaylightSavings( instant ) + .isZero() == requireDst ) + { return instant.getEpochSecond(); } } } ZoneOffset offset = ZoneOffset.systemDefault() - .getRules() - .getOffset(time); - return time.toInstant(offset) - .getEpochSecond(); + .getRules() + .getOffset( time ); + return time.toInstant( offset ) + .getEpochSecond(); } - private static int getField(Map table, String field, int def) throws LuaException { - Object value = table.get(field); - if (value instanceof Number) { + private static int getField( Map table, String field, int def ) throws LuaException + { + Object value = table.get( field ); + if( value instanceof Number ) + { return ((Number) value).intValue(); } - if (def < 0) { - throw new LuaException("field \"" + field + "\" missing in date table"); + if( def < 0 ) + { + throw new LuaException( "field \"" + field + "\" missing in date table" ); } return def; } - private static Boolean getBoolField(Map table, String field) throws LuaException { - Object value = table.get(field); - if (value instanceof Boolean || value == null) { + private static Boolean getBoolField( Map table, String field ) throws LuaException + { + Object value = table.get( field ); + if( value instanceof Boolean || value == null ) + { return (Boolean) value; } - throw new LuaException("field \"" + field + "\" missing in date table"); + throw new LuaException( "field \"" + field + "\" missing in date table" ); } - static Map toTable(TemporalAccessor date, ZoneId offset, Instant instant) { - HashMap table = new HashMap<>(9); - table.put("year", date.getLong(ChronoField.YEAR)); - table.put("month", date.getLong(ChronoField.MONTH_OF_YEAR)); - table.put("day", date.getLong(ChronoField.DAY_OF_MONTH)); - table.put("hour", date.getLong(ChronoField.HOUR_OF_DAY)); - table.put("min", date.getLong(ChronoField.MINUTE_OF_HOUR)); - table.put("sec", date.getLong(ChronoField.SECOND_OF_MINUTE)); - table.put("wday", date.getLong(WeekFields.SUNDAY_START.dayOfWeek())); - table.put("yday", date.getLong(ChronoField.DAY_OF_YEAR)); - table.put("isdst", - offset.getRules() - .isDaylightSavings(instant)); + static Map toTable( TemporalAccessor date, ZoneId offset, Instant instant ) + { + HashMap table = new HashMap<>( 9 ); + table.put( "year", date.getLong( ChronoField.YEAR ) ); + table.put( "month", date.getLong( ChronoField.MONTH_OF_YEAR ) ); + table.put( "day", date.getLong( ChronoField.DAY_OF_MONTH ) ); + table.put( "hour", date.getLong( ChronoField.HOUR_OF_DAY ) ); + table.put( "min", date.getLong( ChronoField.MINUTE_OF_HOUR ) ); + table.put( "sec", date.getLong( ChronoField.SECOND_OF_MINUTE ) ); + table.put( "wday", date.getLong( WeekFields.SUNDAY_START.dayOfWeek() ) ); + table.put( "yday", date.getLong( ChronoField.DAY_OF_YEAR ) ); + table.put( "isdst", + offset.getRules() + .isDaylightSavings( instant ) ); return table; } - private static TemporalField map(TemporalField field, ValueRange range, LongUnaryOperator convert) { - return new TemporalField() { - private final ValueRange range = ValueRange.of(0, 99); + private static TemporalField map( TemporalField field, ValueRange range, LongUnaryOperator convert ) + { + return new TemporalField() + { + private final ValueRange range = ValueRange.of( 0, 99 ); @Override - public TemporalUnit getBaseUnit() { + public TemporalUnit getBaseUnit() + { return field.getBaseUnit(); } @Override - public TemporalUnit getRangeUnit() { + public TemporalUnit getRangeUnit() + { return field.getRangeUnit(); } @Override - public ValueRange range() { + public ValueRange range() + { return this.range; } @Override - public boolean isDateBased() { + public boolean isDateBased() + { return field.isDateBased(); } @Override - public boolean isTimeBased() { + public boolean isTimeBased() + { return field.isTimeBased(); } @Override - public boolean isSupportedBy(TemporalAccessor temporal) { - return field.isSupportedBy(temporal); + public boolean isSupportedBy( TemporalAccessor temporal ) + { + return field.isSupportedBy( temporal ); } @Override - public ValueRange rangeRefinedBy(TemporalAccessor temporal) { + public ValueRange rangeRefinedBy( TemporalAccessor temporal ) + { return this.range; } @Override - public long getFrom(TemporalAccessor temporal) { - return convert.applyAsLong(temporal.getLong(field)); + public long getFrom( TemporalAccessor temporal ) + { + return convert.applyAsLong( temporal.getLong( field ) ); } @Override - @SuppressWarnings ("unchecked") - public R adjustInto(R temporal, long newValue) { - return (R) temporal.with(field, newValue); + @SuppressWarnings( "unchecked" ) + public R adjustInto( R temporal, long newValue ) + { + return (R) temporal.with( field, newValue ); } }; } diff --git a/src/main/java/dan200/computercraft/core/apis/OSAPI.java b/src/main/java/dan200/computercraft/core/apis/OSAPI.java index 27da0462d..c34a8ef7d 100644 --- a/src/main/java/dan200/computercraft/core/apis/OSAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/OSAPI.java @@ -6,23 +6,6 @@ package dan200.computercraft.core.apis; -import static dan200.computercraft.api.lua.LuaValues.checkFinite; - -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatterBuilder; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.TimeZone; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.ILuaAPI; import dan200.computercraft.api.lua.LuaException; @@ -31,12 +14,23 @@ import dan200.computercraft.shared.util.StringUtil; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import javax.annotation.Nonnull; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatterBuilder; +import java.util.*; + +import static dan200.computercraft.api.lua.LuaValues.checkFinite; + /** * The {@link OSAPI} API allows interacting with the current computer. * * @cc.module os */ -public class OSAPI implements ILuaAPI { +public class OSAPI implements ILuaAPI +{ private final IAPIEnvironment apiEnvironment; private final Int2ObjectMap m_alarms = new Int2ObjectOpenHashMap<>(); @@ -46,51 +40,60 @@ public class OSAPI implements ILuaAPI { private int m_nextAlarmToken = 0; - public OSAPI(IAPIEnvironment environment) { + public OSAPI( IAPIEnvironment environment ) + { this.apiEnvironment = environment; } @Override - public String[] getNames() { - return new String[] {"os"}; + public String[] getNames() + { + return new String[] { "os" }; } @Override - public void startup() { + public void startup() + { this.m_time = this.apiEnvironment.getComputerEnvironment() - .getTimeOfDay(); + .getTimeOfDay(); this.m_day = this.apiEnvironment.getComputerEnvironment() - .getDay(); + .getDay(); this.m_clock = 0; - synchronized (this.m_alarms) { + synchronized( this.m_alarms ) + { this.m_alarms.clear(); } } @Override - public void update() { + public void update() + { this.m_clock++; // Wait for all of our alarms - synchronized (this.m_alarms) { + synchronized( this.m_alarms ) + { double previousTime = this.m_time; int previousDay = this.m_day; double time = this.apiEnvironment.getComputerEnvironment() - .getTimeOfDay(); + .getTimeOfDay(); int day = this.apiEnvironment.getComputerEnvironment() - .getDay(); + .getDay(); - if (time > previousTime || day > previousDay) { + if( time > previousTime || day > previousDay ) + { double now = this.m_day * 24.0 + this.m_time; Iterator> it = this.m_alarms.int2ObjectEntrySet() - .iterator(); - while (it.hasNext()) { + .iterator(); + while( it.hasNext() ) + { Int2ObjectMap.Entry entry = it.next(); Alarm alarm = entry.getValue(); double t = alarm.m_day * 24.0 + alarm.m_time; - if (now >= t) { - this.apiEnvironment.queueEvent("alarm", entry.getIntKey()); + if( now >= t ) + { + this.apiEnvironment.queueEvent( "alarm", entry.getIntKey() ); it.remove(); } } @@ -102,8 +105,10 @@ public class OSAPI implements ILuaAPI { } @Override - public void shutdown() { - synchronized (this.m_alarms) { + public void shutdown() + { + synchronized( this.m_alarms ) + { this.m_alarms.clear(); } } @@ -118,10 +123,11 @@ public class OSAPI implements ILuaAPI { * @cc.see os.pullEvent To pull the event queued */ @LuaFunction - public final void queueEvent(String name, IArguments args) { - this.apiEnvironment.queueEvent(name, - args.drop(1) - .getAll()); + public final void queueEvent( String name, IArguments args ) + { + this.apiEnvironment.queueEvent( name, + args.drop( 1 ) + .getAll() ); } /** @@ -133,8 +139,9 @@ public class OSAPI implements ILuaAPI { * @throws LuaException If the time is below zero. */ @LuaFunction - public final int startTimer(double timer) throws LuaException { - return this.apiEnvironment.startTimer(Math.round(checkFinite(0, timer) / 0.05)); + public final int startTimer( double timer ) throws LuaException + { + return this.apiEnvironment.startTimer( Math.round( checkFinite( 0, timer ) / 0.05 ) ); } /** @@ -144,8 +151,9 @@ public class OSAPI implements ILuaAPI { * @see #startTimer To start a timer. */ @LuaFunction - public final void cancelTimer(int token) { - this.apiEnvironment.cancelTimer(token); + public final void cancelTimer( int token ) + { + this.apiEnvironment.cancelTimer( token ); } /** @@ -156,14 +164,17 @@ public class OSAPI implements ILuaAPI { * @throws LuaException If the time is out of range. */ @LuaFunction - public final int setAlarm(double time) throws LuaException { - checkFinite(0, time); - if (time < 0.0 || time >= 24.0) { - throw new LuaException("Number out of range"); + public final int setAlarm( double time ) throws LuaException + { + checkFinite( 0, time ); + if( time < 0.0 || time >= 24.0 ) + { + throw new LuaException( "Number out of range" ); } - synchronized (this.m_alarms) { + synchronized( this.m_alarms ) + { int day = time > this.m_time ? this.m_day : this.m_day + 1; - this.m_alarms.put(this.m_nextAlarmToken, new Alarm(time, day)); + this.m_alarms.put( this.m_nextAlarmToken, new Alarm( time, day ) ); return this.m_nextAlarmToken++; } } @@ -175,25 +186,29 @@ public class OSAPI implements ILuaAPI { * @see #setAlarm To set an alarm. */ @LuaFunction - public final void cancelAlarm(int token) { - synchronized (this.m_alarms) { - this.m_alarms.remove(token); + public final void cancelAlarm( int token ) + { + synchronized( this.m_alarms ) + { + this.m_alarms.remove( token ); } } /** * Shuts down the computer immediately. */ - @LuaFunction ("shutdown") - public final void doShutdown() { + @LuaFunction( "shutdown" ) + public final void doShutdown() + { this.apiEnvironment.shutdown(); } /** * Reboots the computer immediately. */ - @LuaFunction ("reboot") - public final void doReboot() { + @LuaFunction( "reboot" ) + public final void doReboot() + { this.apiEnvironment.reboot(); } @@ -202,11 +217,12 @@ public class OSAPI implements ILuaAPI { * * @return The ID of the computer. */ - @LuaFunction ({ + @LuaFunction( { "getComputerID", "computerID" - }) - public final int getComputerID() { + } ) + public final int getComputerID() + { return this.apiEnvironment.getComputerID(); } @@ -216,13 +232,14 @@ public class OSAPI implements ILuaAPI { * @return The label of the computer. * @cc.treturn string The label of the computer. */ - @LuaFunction ({ + @LuaFunction( { "getComputerLabel", "computerLabel" - }) - public final Object[] getComputerLabel() { + } ) + public final Object[] getComputerLabel() + { String label = this.apiEnvironment.getLabel(); - return label == null ? null : new Object[] {label}; + return label == null ? null : new Object[] { label }; } /** @@ -231,8 +248,9 @@ public class OSAPI implements ILuaAPI { * @param label The new label. May be {@code nil} in order to clear it. */ @LuaFunction - public final void setComputerLabel(Optional label) { - this.apiEnvironment.setLabel(StringUtil.normaliseLabel(label.orElse(null))); + public final void setComputerLabel( Optional label ) + { + this.apiEnvironment.setLabel( StringUtil.normaliseLabel( label.orElse( null ) ) ); } /** @@ -241,7 +259,8 @@ public class OSAPI implements ILuaAPI { * @return The computer's uptime. */ @LuaFunction - public final double clock() { + public final double clock() + { return this.m_clock * 0.05; } @@ -258,33 +277,37 @@ public class OSAPI implements ILuaAPI { * @return The hour of the selected locale, or a UNIX timestamp from the table, depending on the argument passed in. * @throws LuaException If an invalid locale is passed. * @cc.tparam [opt] string|table locale The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} - * locale if not specified. + * locale if not specified. * @see #date To get a date table that can be converted with this function. */ @LuaFunction - public final Object time(IArguments args) throws LuaException { - Object value = args.get(0); - if (value instanceof Map) { - return LuaDateTime.fromTable((Map) value); + public final Object time( IArguments args ) throws LuaException + { + Object value = args.get( 0 ); + if( value instanceof Map ) + { + return LuaDateTime.fromTable( (Map) value ); } - String param = args.optString(0, "ingame"); - switch (param.toLowerCase(Locale.ROOT)) { - case "utc": // Get Hour of day (UTC) - return getTimeForCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC"))); - case "local": // Get Hour of day (local time) - return getTimeForCalendar(Calendar.getInstance()); - case "ingame": // Get in-game hour - return this.m_time; - default: - throw new LuaException("Unsupported operation"); + String param = args.optString( 0, "ingame" ); + switch( param.toLowerCase( Locale.ROOT ) ) + { + case "utc": // Get Hour of day (UTC) + return getTimeForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); + case "local": // Get Hour of day (local time) + return getTimeForCalendar( Calendar.getInstance() ); + case "ingame": // Get in-game hour + return this.m_time; + default: + throw new LuaException( "Unsupported operation" ); } } - private static float getTimeForCalendar(Calendar c) { - float time = c.get(Calendar.HOUR_OF_DAY); - time += c.get(Calendar.MINUTE) / 60.0f; - time += c.get(Calendar.SECOND) / (60.0f * 60.0f); + private static float getTimeForCalendar( Calendar c ) + { + float time = c.get( Calendar.HOUR_OF_DAY ); + time += c.get( Calendar.MINUTE ) / 60.0f; + time += c.get( Calendar.SECOND ) / (60.0f * 60.0f); return time; } @@ -300,28 +323,32 @@ public class OSAPI implements ILuaAPI { * @throws LuaException If an invalid locale is passed. */ @LuaFunction - public final int day(Optional args) throws LuaException { - switch (args.orElse("ingame") - .toLowerCase(Locale.ROOT)) { - case "utc": // Get numbers of days since 1970-01-01 (utc) - return getDayForCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC"))); - case "local": // Get numbers of days since 1970-01-01 (local time) - return getDayForCalendar(Calendar.getInstance()); - case "ingame":// Get game day - return this.m_day; - default: - throw new LuaException("Unsupported operation"); + public final int day( Optional args ) throws LuaException + { + switch( args.orElse( "ingame" ) + .toLowerCase( Locale.ROOT ) ) + { + case "utc": // Get numbers of days since 1970-01-01 (utc) + return getDayForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); + case "local": // Get numbers of days since 1970-01-01 (local time) + return getDayForCalendar( Calendar.getInstance() ); + case "ingame":// Get game day + return this.m_day; + default: + throw new LuaException( "Unsupported operation" ); } } - private static int getDayForCalendar(Calendar c) { + private static int getDayForCalendar( Calendar c ) + { GregorianCalendar g = c instanceof GregorianCalendar ? (GregorianCalendar) c : new GregorianCalendar(); - int year = c.get(Calendar.YEAR); + int year = c.get( Calendar.YEAR ); int day = 0; - for (int y = 1970; y < year; y++) { - day += g.isLeapYear(y) ? 366 : 365; + for( int y = 1970; y < year; y++ ) + { + day += g.isLeapYear( y ) ? 366 : 365; } - day += c.get(Calendar.DAY_OF_YEAR); + day += c.get( Calendar.DAY_OF_YEAR ); return day; } @@ -337,32 +364,38 @@ public class OSAPI implements ILuaAPI { * @throws LuaException If an invalid locale is passed. */ @LuaFunction - public final long epoch(Optional args) throws LuaException { - switch (args.orElse("ingame") - .toLowerCase(Locale.ROOT)) { - case "utc": { - // Get utc epoch - Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - return getEpochForCalendar(c); - } - case "local": { - // Get local epoch - Calendar c = Calendar.getInstance(); - return getEpochForCalendar(c); - } - case "ingame": - // Get in-game epoch - synchronized (this.m_alarms) { - return this.m_day * 86400000L + (long) (this.m_time * 3600000.0); + public final long epoch( Optional args ) throws LuaException + { + switch( args.orElse( "ingame" ) + .toLowerCase( Locale.ROOT ) ) + { + case "utc": + { + // Get utc epoch + Calendar c = Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ); + return getEpochForCalendar( c ); } - default: - throw new LuaException("Unsupported operation"); + case "local": + { + // Get local epoch + Calendar c = Calendar.getInstance(); + return getEpochForCalendar( c ); + } + case "ingame": + // Get in-game epoch + synchronized( this.m_alarms ) + { + return this.m_day * 86400000L + (long) (this.m_time * 3600000.0); + } + default: + throw new LuaException( "Unsupported operation" ); } } - private static long getEpochForCalendar(Calendar c) { + private static long getEpochForCalendar( Calendar c ) + { return c.getTime() - .getTime(); + .getTime(); } /** @@ -376,54 +409,62 @@ public class OSAPI implements ILuaAPI { * UNIX timestamp (days since 1 January 1970) with {@link #date}. * * @param formatA The format of the string to return. This defaults to {@code %c}, which expands to a string similar to "Sat Dec 24 16:58:00 2011". - * @param timeA The time to convert to a string. This defaults to the current time. + * @param timeA The time to convert to a string. This defaults to the current time. * @return The resulting format string. * @throws LuaException If an invalid format is passed. */ @LuaFunction - public final Object date(Optional formatA, Optional timeA) throws LuaException { - String format = formatA.orElse("%c"); - long time = timeA.orElseGet(() -> Instant.now() - .getEpochSecond()); + public final Object date( Optional formatA, Optional timeA ) throws LuaException + { + String format = formatA.orElse( "%c" ); + long time = timeA.orElseGet( () -> Instant.now() + .getEpochSecond() ); - Instant instant = Instant.ofEpochSecond(time); + Instant instant = Instant.ofEpochSecond( time ); ZonedDateTime date; ZoneOffset offset; - if (format.startsWith("!")) { + if( format.startsWith( "!" ) ) + { offset = ZoneOffset.UTC; - date = ZonedDateTime.ofInstant(instant, offset); - format = format.substring(1); - } else { + date = ZonedDateTime.ofInstant( instant, offset ); + format = format.substring( 1 ); + } + else + { ZoneId id = ZoneId.systemDefault(); offset = id.getRules() - .getOffset(instant); - date = ZonedDateTime.ofInstant(instant, id); + .getOffset( instant ); + date = ZonedDateTime.ofInstant( instant, id ); } - if (format.equals("*t")) { - return LuaDateTime.toTable(date, offset, instant); + if( format.equals( "*t" ) ) + { + return LuaDateTime.toTable( date, offset, instant ); } DateTimeFormatterBuilder formatter = new DateTimeFormatterBuilder(); - LuaDateTime.format(formatter, format, offset); - return formatter.toFormatter(Locale.ROOT) - .format(date); + LuaDateTime.format( formatter, format, offset ); + return formatter.toFormatter( Locale.ROOT ) + .format( date ); } - private static class Alarm implements Comparable { + private static class Alarm implements Comparable + { final double m_time; final int m_day; - Alarm(double time, int day) { + Alarm( double time, int day ) + { this.m_time = time; this.m_day = day; } @Override - public int compareTo(@Nonnull Alarm o) { + public int compareTo( @Nonnull Alarm o ) + { double t = this.m_day * 24.0 + this.m_time; double ot = this.m_day * 24.0 + this.m_time; - return Double.compare(t, ot); + return Double.compare( t, ot ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java index 916aa4541..58c40004e 100644 --- a/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java @@ -6,24 +6,9 @@ package dan200.computercraft.core.apis; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -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.IArguments; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.lua.*; import dan200.computercraft.api.peripheral.IDynamicPeripheral; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IWorkMonitor; @@ -34,35 +19,45 @@ import dan200.computercraft.core.asm.PeripheralMethod; import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.core.tracking.TrackingField; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; + /** * CC's "native" peripheral API. This is wrapped within CraftOS to provide a version which works with modems. * * @cc.module peripheral * @hidden */ -public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener { +public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener +{ private final IAPIEnvironment environment; private final PeripheralWrapper[] peripherals = new PeripheralWrapper[6]; private boolean running; - public PeripheralAPI(IAPIEnvironment environment) { + + public PeripheralAPI( IAPIEnvironment environment ) + { this.environment = environment; - this.environment.setPeripheralChangeListener(this); + this.environment.setPeripheralChangeListener( this ); this.running = false; } - public static Map getMethods(IPeripheral peripheral) { - String[] dynamicMethods = peripheral instanceof IDynamicPeripheral ? Objects.requireNonNull(((IDynamicPeripheral) peripheral).getMethodNames(), - "Peripheral methods cannot be null") : - LuaMethod.EMPTY_METHODS; + public static Map getMethods( IPeripheral peripheral ) + { + String[] dynamicMethods = peripheral instanceof IDynamicPeripheral ? Objects.requireNonNull( ((IDynamicPeripheral) peripheral).getMethodNames(), + "Peripheral methods cannot be null" ) : + LuaMethod.EMPTY_METHODS; - List> methods = PeripheralMethod.GENERATOR.getMethods(peripheral.getClass()); + List> methods = PeripheralMethod.GENERATOR.getMethods( peripheral.getClass() ); - Map methodMap = new HashMap<>(methods.size() + dynamicMethods.length); - for (int i = 0; i < dynamicMethods.length; i++) { - methodMap.put(dynamicMethods[i], PeripheralMethod.DYNAMIC.get(i)); + Map methodMap = new HashMap<>( methods.size() + dynamicMethods.length ); + for( int i = 0; i < dynamicMethods.length; i++ ) + { + methodMap.put( dynamicMethods[i], PeripheralMethod.DYNAMIC.get( i ) ); } - for (NamedMethod method : methods) { - methodMap.put(method.getName(), method.getMethod()); + for( NamedMethod method : methods ) + { + methodMap.put( method.getName(), method.getMethod() ); } return methodMap; } @@ -70,48 +65,59 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange // IPeripheralChangeListener @Override - public void onPeripheralChanged(ComputerSide side, IPeripheral newPeripheral) { - synchronized (this.peripherals) { + public void onPeripheralChanged( ComputerSide side, IPeripheral newPeripheral ) + { + synchronized( this.peripherals ) + { int index = side.ordinal(); - if (this.peripherals[index] != null) { + if( this.peripherals[index] != null ) + { // Queue a detachment final PeripheralWrapper wrapper = this.peripherals[index]; - if (wrapper.isAttached()) { + if( wrapper.isAttached() ) + { wrapper.detach(); } // Queue a detachment event - this.environment.queueEvent("peripheral_detach", side.getName()); + this.environment.queueEvent( "peripheral_detach", side.getName() ); } // Assign the new peripheral - this.peripherals[index] = newPeripheral == null ? null : new PeripheralWrapper(newPeripheral, side.getName()); + this.peripherals[index] = newPeripheral == null ? null : new PeripheralWrapper( newPeripheral, side.getName() ); - if (this.peripherals[index] != null) { + if( this.peripherals[index] != null ) + { // Queue an attachment final PeripheralWrapper wrapper = this.peripherals[index]; - if (this.running && !wrapper.isAttached()) { + if( this.running && !wrapper.isAttached() ) + { wrapper.attach(); } // Queue an attachment event - this.environment.queueEvent("peripheral", side.getName()); + this.environment.queueEvent( "peripheral", side.getName() ); } } } @Override - public String[] getNames() { - return new String[] {"peripheral"}; + public String[] getNames() + { + return new String[] { "peripheral" }; } @Override - public void startup() { - synchronized (this.peripherals) { + public void startup() + { + synchronized( this.peripherals ) + { this.running = true; - for (int i = 0; i < 6; i++) { + for( int i = 0; i < 6; i++ ) + { PeripheralWrapper wrapper = this.peripherals[i]; - if (wrapper != null && !wrapper.isAttached()) { + if( wrapper != null && !wrapper.isAttached() ) + { wrapper.attach(); } } @@ -119,12 +125,16 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange } @Override - public void shutdown() { - synchronized (this.peripherals) { + public void shutdown() + { + synchronized( this.peripherals ) + { this.running = false; - for (int i = 0; i < 6; i++) { + for( int i = 0; i < 6; i++ ) + { PeripheralWrapper wrapper = this.peripherals[i]; - if (wrapper != null && wrapper.isAttached()) { + if( wrapper != null && wrapper.isAttached() ) + { wrapper.detach(); } } @@ -132,12 +142,16 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange } @LuaFunction - public final boolean isPresent(String sideName) { - ComputerSide side = ComputerSide.valueOfInsensitive(sideName); - if (side != null) { - synchronized (this.peripherals) { + public final boolean isPresent( String sideName ) + { + ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); + if( side != null ) + { + synchronized( this.peripherals ) + { PeripheralWrapper p = this.peripherals[side.ordinal()]; - if (p != null) { + if( p != null ) + { return true; } } @@ -146,69 +160,86 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange } @LuaFunction - public final Object[] getType(String sideName) { - ComputerSide side = ComputerSide.valueOfInsensitive(sideName); - if (side == null) { + public final Object[] getType( String sideName ) + { + ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); + if( side == null ) + { return null; } - synchronized (this.peripherals) { + synchronized( this.peripherals ) + { PeripheralWrapper p = this.peripherals[side.ordinal()]; - if (p != null) { - return new Object[] {p.getType()}; + if( p != null ) + { + return new Object[] { p.getType() }; } } return null; } @LuaFunction - public final Object[] getMethods(String sideName) { - ComputerSide side = ComputerSide.valueOfInsensitive(sideName); - if (side == null) { + public final Object[] getMethods( String sideName ) + { + ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); + if( side == null ) + { return null; } - synchronized (this.peripherals) { + synchronized( this.peripherals ) + { PeripheralWrapper p = this.peripherals[side.ordinal()]; - if (p != null) { - return new Object[] {p.getMethods()}; + if( p != null ) + { + return new Object[] { p.getMethods() }; } } return null; } @LuaFunction - public final MethodResult call(ILuaContext context, IArguments args) throws LuaException { - ComputerSide side = ComputerSide.valueOfInsensitive(args.getString(0)); - String methodName = args.getString(1); - IArguments methodArgs = args.drop(2); + public final MethodResult call( ILuaContext context, IArguments args ) throws LuaException + { + ComputerSide side = ComputerSide.valueOfInsensitive( args.getString( 0 ) ); + String methodName = args.getString( 1 ); + IArguments methodArgs = args.drop( 2 ); - if (side == null) { - throw new LuaException("No peripheral attached"); + if( side == null ) + { + throw new LuaException( "No peripheral attached" ); } PeripheralWrapper p; - synchronized (this.peripherals) { + synchronized( this.peripherals ) + { p = this.peripherals[side.ordinal()]; } - if (p == null) { - throw new LuaException("No peripheral attached"); + if( p == null ) + { + throw new LuaException( "No peripheral attached" ); } - try { - return p.call(context, methodName, methodArgs) - .adjustError(1); - } catch (LuaException e) { + try + { + return p.call( context, methodName, methodArgs ) + .adjustError( 1 ); + } + catch( LuaException e ) + { // We increase the error level by one in order to shift the error level to where peripheral.call was // invoked. It would be possible to do it in Lua code, but would add significantly more overhead. - if (e.getLevel() > 0) { - throw new FastLuaException(e.getMessage(), e.getLevel() + 1); + if( e.getLevel() > 0 ) + { + throw new FastLuaException( e.getMessage(), e.getLevel() + 1 ); } throw e; } } - private class PeripheralWrapper extends ComputerAccess { + private class PeripheralWrapper extends ComputerAccess + { private final String side; private final IPeripheral peripheral; @@ -216,116 +247,144 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange private final Map methodMap; private boolean attached; - PeripheralWrapper(IPeripheral peripheral, String side) { - super(PeripheralAPI.this.environment); + PeripheralWrapper( IPeripheral peripheral, String side ) + { + super( PeripheralAPI.this.environment ); this.side = side; this.peripheral = peripheral; this.attached = false; - this.type = Objects.requireNonNull(peripheral.getType(), "Peripheral type cannot be null"); + this.type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); - this.methodMap = PeripheralAPI.getMethods(peripheral); + this.methodMap = PeripheralAPI.getMethods( peripheral ); } - public String getType() { + public String getType() + { return this.type; - } public IPeripheral getPeripheral() { + } + + public IPeripheral getPeripheral() + { return this.peripheral; } - public Collection getMethods() { + public Collection getMethods() + { return this.methodMap.keySet(); } - public synchronized void attach() { + public synchronized void attach() + { this.attached = true; - this.peripheral.attach(this); + this.peripheral.attach( this ); } - public void detach() { + public void detach() + { // Call detach - this.peripheral.detach(this); + this.peripheral.detach( this ); - synchronized (this) { + synchronized( this ) + { // Unmount everything the detach function forgot to do this.unmountAll(); } this.attached = false; - } public synchronized boolean isAttached() { + } + + public synchronized boolean isAttached() + { return this.attached; } - public MethodResult call(ILuaContext context, String methodName, IArguments arguments) throws LuaException { + public MethodResult call( ILuaContext context, String methodName, IArguments arguments ) throws LuaException + { PeripheralMethod method; - synchronized (this) { - method = this.methodMap.get(methodName); + synchronized( this ) + { + method = this.methodMap.get( methodName ); } - if (method == null) { - throw new LuaException("No such method " + methodName); + if( method == null ) + { + throw new LuaException( "No such method " + methodName ); } - PeripheralAPI.this.environment.addTrackingChange(TrackingField.PERIPHERAL_OPS); - return method.apply(this.peripheral, context, this, arguments); + PeripheralAPI.this.environment.addTrackingChange( TrackingField.PERIPHERAL_OPS ); + return method.apply( this.peripheral, context, this, arguments ); } // IComputerAccess implementation @Override - public synchronized String mount(@Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName) { - if (!this.attached) { + public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName ) + { + if( !this.attached ) + { throw new NotAttachedException(); } - return super.mount(desiredLoc, mount, driveName); + return super.mount( desiredLoc, mount, driveName ); } @Override - public synchronized String mountWritable(@Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName) { - if (!this.attached) { + public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName ) + { + if( !this.attached ) + { throw new NotAttachedException(); } - return super.mountWritable(desiredLoc, mount, driveName); + return super.mountWritable( desiredLoc, mount, driveName ); } @Override - public synchronized void unmount(String location) { - if (!this.attached) { + public synchronized void unmount( String location ) + { + if( !this.attached ) + { throw new NotAttachedException(); } - super.unmount(location); + super.unmount( location ); } @Override - public int getID() { - if (!this.attached) { + public int getID() + { + if( !this.attached ) + { throw new NotAttachedException(); } return super.getID(); } @Override - public void queueEvent(@Nonnull String event, Object... arguments) { - if (!this.attached) { + public void queueEvent( @Nonnull String event, Object... arguments ) + { + if( !this.attached ) + { throw new NotAttachedException(); } - super.queueEvent(event, arguments); + super.queueEvent( event, arguments ); } @Nonnull @Override - public IWorkMonitor getMainThreadMonitor() { - if (!this.attached) { + public IWorkMonitor getMainThreadMonitor() + { + if( !this.attached ) + { throw new NotAttachedException(); } return super.getMainThreadMonitor(); } - @Nonnull @Override - public String getAttachmentName() { - if (!this.attached) { + public String getAttachmentName() + { + if( !this.attached ) + { throw new NotAttachedException(); } return this.side; @@ -333,31 +392,39 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange @Nonnull @Override - public Map getAvailablePeripherals() { - if (!this.attached) { + public Map getAvailablePeripherals() + { + if( !this.attached ) + { throw new NotAttachedException(); } Map peripherals = new HashMap<>(); - for (PeripheralWrapper wrapper : PeripheralAPI.this.peripherals) { - if (wrapper != null && wrapper.isAttached()) { - peripherals.put(wrapper.getAttachmentName(), wrapper.getPeripheral()); + for( PeripheralWrapper wrapper : PeripheralAPI.this.peripherals ) + { + if( wrapper != null && wrapper.isAttached() ) + { + peripherals.put( wrapper.getAttachmentName(), wrapper.getPeripheral() ); } } - return Collections.unmodifiableMap(peripherals); + return Collections.unmodifiableMap( peripherals ); } @Nullable @Override - public IPeripheral getAvailablePeripheral(@Nonnull String name) { - if (!this.attached) { + public IPeripheral getAvailablePeripheral( @Nonnull String name ) + { + if( !this.attached ) + { throw new NotAttachedException(); } - for (PeripheralWrapper wrapper : PeripheralAPI.this.peripherals) { - if (wrapper != null && wrapper.isAttached() && wrapper.getAttachmentName() - .equals(name)) { + for( PeripheralWrapper wrapper : PeripheralAPI.this.peripherals ) + { + if( wrapper != null && wrapper.isAttached() && wrapper.getAttachmentName() + .equals( name ) ) + { return wrapper.getPeripheral(); } } diff --git a/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java b/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java index 9f026729a..90cedcfe7 100644 --- a/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java @@ -26,7 +26,7 @@ import dan200.computercraft.core.computer.ComputerSide; * * @cc.usage Toggle the redstone signal above the computer every 0.5 seconds. * - *
+ * 
  *     while true do
  *       redstone.setOutput("top", not redstone.getOutput("top"))
  *       sleep(0.5)
@@ -34,7 +34,7 @@ import dan200.computercraft.core.computer.ComputerSide;
  *     
* @cc.usage Mimic a redstone comparator in [subtraction mode][comparator]. * - *
+ * 
  *     while true do
  *       local rear = rs.getAnalogueInput("back")
  *       local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
@@ -44,18 +44,21 @@ import dan200.computercraft.core.computer.ComputerSide;
  *     end
  *     
* - * [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on the Minecraft wiki." + * [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on the Minecraft wiki." * @cc.module redstone */ -public class RedstoneAPI implements ILuaAPI { +public class RedstoneAPI implements ILuaAPI +{ private final IAPIEnvironment environment; - public RedstoneAPI(IAPIEnvironment environment) { + public RedstoneAPI( IAPIEnvironment environment ) + { this.environment = environment; } @Override - public String[] getNames() { + public String[] getNames() + { return new String[] { "rs", "redstone" @@ -68,7 +71,8 @@ public class RedstoneAPI implements ILuaAPI { * @return A table of valid sides. */ @LuaFunction - public final String[] getSides() { + public final String[] getSides() + { return ComputerSide.NAMES; } @@ -76,11 +80,12 @@ public class RedstoneAPI implements ILuaAPI { * Turn the redstone signal of a specific side on or off. * * @param side The side to set. - * @param on Whether the redstone signal should be on or off. When on, a signal strength of 15 is emitted. + * @param on Whether the redstone signal should be on or off. When on, a signal strength of 15 is emitted. */ @LuaFunction - public final void setOutput(ComputerSide side, boolean on) { - this.environment.setOutput(side, on ? 15 : 0); + public final void setOutput( ComputerSide side, boolean on ) + { + this.environment.setOutput( side, on ? 15 : 0 ); } /** @@ -91,8 +96,9 @@ public class RedstoneAPI implements ILuaAPI { * @see #setOutput */ @LuaFunction - public final boolean getOutput(ComputerSide side) { - return this.environment.getOutput(side) > 0; + public final boolean getOutput( ComputerSide side ) + { + return this.environment.getOutput( side ) > 0; } /** @@ -102,26 +108,29 @@ public class RedstoneAPI implements ILuaAPI { * @return Whether the redstone input is on or off. */ @LuaFunction - public final boolean getInput(ComputerSide side) { - return this.environment.getInput(side) > 0; + public final boolean getInput( ComputerSide side ) + { + return this.environment.getInput( side ) > 0; } /** * Set the redstone signal strength for a specific side. * - * @param side The side to set. + * @param side The side to set. * @param value The signal strength between 0 and 15. * @throws LuaException If {@code value} is not betwene 0 and 15. */ - @LuaFunction ({ + @LuaFunction( { "setAnalogOutput", "setAnalogueOutput" - }) - public final void setAnalogOutput(ComputerSide side, int value) throws LuaException { - if (value < 0 || value > 15) { - throw new LuaException("Expected number in range 0-15"); + } ) + public final void setAnalogOutput( ComputerSide side, int value ) throws LuaException + { + if( value < 0 || value > 15 ) + { + throw new LuaException( "Expected number in range 0-15" ); } - this.environment.setOutput(side, value); + this.environment.setOutput( side, value ); } /** @@ -131,12 +140,13 @@ public class RedstoneAPI implements ILuaAPI { * @return The output signal strength, between 0 and 15. * @see #setAnalogOutput */ - @LuaFunction ({ + @LuaFunction( { "getAnalogOutput", "getAnalogueOutput" - }) - public final int getAnalogOutput(ComputerSide side) { - return this.environment.getOutput(side); + } ) + public final int getAnalogOutput( ComputerSide side ) + { + return this.environment.getOutput( side ); } /** @@ -145,25 +155,27 @@ public class RedstoneAPI implements ILuaAPI { * @param side The side to get. * @return The input signal strength, between 0 and 15. */ - @LuaFunction ({ + @LuaFunction( { "getAnalogInput", "getAnalogueInput" - }) - public final int getAnalogInput(ComputerSide side) { - return this.environment.getInput(side); + } ) + public final int getAnalogInput( ComputerSide side ) + { + return this.environment.getInput( side ); } /** * Set the bundled cable output for a specific side. * - * @param side The side to set. + * @param side The side to set. * @param output The colour bitmask to set. * @cc.see colors.subtract For removing a colour from the bitmask. * @cc.see colors.combine For adding a color to the bitmask. */ @LuaFunction - public final void setBundledOutput(ComputerSide side, int output) { - this.environment.setBundledOutput(side, output); + public final void setBundledOutput( ComputerSide side, int output ) + { + this.environment.setBundledOutput( side, output ); } /** @@ -173,8 +185,9 @@ public class RedstoneAPI implements ILuaAPI { * @return The bundle cable's output. */ @LuaFunction - public final int getBundledOutput(ComputerSide side) { - return this.environment.getBundledOutput(side); + public final int getBundledOutput( ComputerSide side ) + { + return this.environment.getBundledOutput( side ); } /** @@ -197,14 +210,15 @@ public class RedstoneAPI implements ILuaAPI { * @param mask The mask to test. * @return If the colours are on. * @cc.usage Check if @{colors.white} and @{colors.black} are on above the computer. - *
+     * 
      *     print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
      *     
* @see #getBundledInput */ @LuaFunction - public final boolean testBundledInput(ComputerSide side, int mask) { - int input = this.environment.getBundledInput(side); + public final boolean testBundledInput( ComputerSide side, int mask ) + { + int input = this.environment.getBundledInput( side ); return (input & mask) == mask; } } diff --git a/src/main/java/dan200/computercraft/core/apis/TableHelper.java b/src/main/java/dan200/computercraft/core/apis/TableHelper.java index d3766b337..cb584cd23 100644 --- a/src/main/java/dan200/computercraft/core/apis/TableHelper.java +++ b/src/main/java/dan200/computercraft/core/apis/TableHelper.java @@ -6,150 +6,207 @@ package dan200.computercraft.core.apis; -import static dan200.computercraft.api.lua.LuaValues.getNumericType; - -import java.util.Map; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaValues; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Map; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaValues; +import static dan200.computercraft.api.lua.LuaValues.getNumericType; /** * Various helpers for tables. */ -public final class TableHelper { - private TableHelper() { - throw new IllegalStateException("Cannot instantiate singleton " + this.getClass().getName()); +public final class TableHelper +{ + private TableHelper() + { + throw new IllegalStateException( "Cannot instantiate singleton " + this.getClass().getName() ); } - public static int getIntField(@Nonnull Map table, @Nonnull String key) throws LuaException { - Object value = table.get(key); - if (value instanceof Number) { + public static int getIntField( @Nonnull Map table, @Nonnull String key ) throws LuaException + { + Object value = table.get( key ); + if( value instanceof Number ) + { return (int) ((Number) value).longValue(); - } else { - throw badKey(key, "number", value); + } + else + { + throw badKey( key, "number", value ); } } @Nonnull - public static LuaException badKey(@Nonnull String key, @Nonnull String expected, @Nullable Object actual) { - return badKey(key, expected, LuaValues.getType(actual)); + public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nullable Object actual ) + { + return badKey( key, expected, LuaValues.getType( actual ) ); } @Nonnull - public static LuaException badKey(@Nonnull String key, @Nonnull String expected, @Nonnull String actual) { - return new LuaException("bad field '" + key + "' (" + expected + " expected, got " + actual + ")"); + public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nonnull String actual ) + { + return new LuaException( "bad field '" + key + "' (" + expected + " expected, got " + actual + ")" ); } - public static double getRealField(@Nonnull Map table, @Nonnull String key) throws LuaException { - return checkReal(key, getNumberField(table, key)); + public static double getRealField( @Nonnull Map table, @Nonnull String key ) throws LuaException + { + return checkReal( key, getNumberField( table, key ) ); } - private static double checkReal(@Nonnull String key, double value) throws LuaException { - if (!Double.isFinite(value)) { - throw badKey(key, "number", getNumericType(value)); + private static double checkReal( @Nonnull String key, double value ) throws LuaException + { + if( !Double.isFinite( value ) ) + { + throw badKey( key, "number", getNumericType( value ) ); } return value; } - public static double getNumberField(@Nonnull Map table, @Nonnull String key) throws LuaException { - Object value = table.get(key); - if (value instanceof Number) { + public static double getNumberField( @Nonnull Map table, @Nonnull String key ) throws LuaException + { + Object value = table.get( key ); + if( value instanceof Number ) + { return ((Number) value).doubleValue(); - } else { - throw badKey(key, "number", value); + } + else + { + throw badKey( key, "number", value ); } } - public static boolean getBooleanField(@Nonnull Map table, @Nonnull String key) throws LuaException { - Object value = table.get(key); - if (value instanceof Boolean) { + public static boolean getBooleanField( @Nonnull Map table, @Nonnull String key ) throws LuaException + { + Object value = table.get( key ); + if( value instanceof Boolean ) + { return (Boolean) value; - } else { - throw badKey(key, "boolean", value); + } + else + { + throw badKey( key, "boolean", value ); } } @Nonnull - public static String getStringField(@Nonnull Map table, @Nonnull String key) throws LuaException { - Object value = table.get(key); - if (value instanceof String) { + public static String getStringField( @Nonnull Map table, @Nonnull String key ) throws LuaException + { + Object value = table.get( key ); + if( value instanceof String ) + { return (String) value; - } else { - throw badKey(key, "string", value); + } + else + { + throw badKey( key, "string", value ); } } - @SuppressWarnings ("unchecked") + @SuppressWarnings( "unchecked" ) @Nonnull - public static Map getTableField(@Nonnull Map table, @Nonnull String key) throws LuaException { - Object value = table.get(key); - if (value instanceof Map) { + public static Map getTableField( @Nonnull Map table, @Nonnull String key ) throws LuaException + { + Object value = table.get( key ); + if( value instanceof Map ) + { return (Map) value; - } else { - throw badKey(key, "table", value); + } + else + { + throw badKey( key, "table", value ); } } - public static int optIntField(@Nonnull Map table, @Nonnull String key, int def) throws LuaException { - Object value = table.get(key); - if (value == null) { + public static int optIntField( @Nonnull Map table, @Nonnull String key, int def ) throws LuaException + { + Object value = table.get( key ); + if( value == null ) + { return def; - } else if (value instanceof Number) { + } + else if( value instanceof Number ) + { return (int) ((Number) value).longValue(); - } else { - throw badKey(key, "number", value); + } + else + { + throw badKey( key, "number", value ); } } - public static double optRealField(@Nonnull Map table, @Nonnull String key, double def) throws LuaException { - return checkReal(key, optNumberField(table, key, def)); + public static double optRealField( @Nonnull Map table, @Nonnull String key, double def ) throws LuaException + { + return checkReal( key, optNumberField( table, key, def ) ); } - public static double optNumberField(@Nonnull Map table, @Nonnull String key, double def) throws LuaException { - Object value = table.get(key); - if (value == null) { + public static double optNumberField( @Nonnull Map table, @Nonnull String key, double def ) throws LuaException + { + Object value = table.get( key ); + if( value == null ) + { return def; - } else if (value instanceof Number) { + } + else if( value instanceof Number ) + { return ((Number) value).doubleValue(); - } else { - throw badKey(key, "number", value); + } + else + { + throw badKey( key, "number", value ); } } - public static boolean optBooleanField(@Nonnull Map table, @Nonnull String key, boolean def) throws LuaException { - Object value = table.get(key); - if (value == null) { + public static boolean optBooleanField( @Nonnull Map table, @Nonnull String key, boolean def ) throws LuaException + { + Object value = table.get( key ); + if( value == null ) + { return def; - } else if (value instanceof Boolean) { + } + else if( value instanceof Boolean ) + { return (Boolean) value; - } else { - throw badKey(key, "boolean", value); + } + else + { + throw badKey( key, "boolean", value ); } } - public static String optStringField(@Nonnull Map table, @Nonnull String key, String def) throws LuaException { - Object value = table.get(key); - if (value == null) { + public static String optStringField( @Nonnull Map table, @Nonnull String key, String def ) throws LuaException + { + Object value = table.get( key ); + if( value == null ) + { return def; - } else if (value instanceof String) { + } + else if( value instanceof String ) + { return (String) value; - } else { - throw badKey(key, "string", value); + } + else + { + throw badKey( key, "string", value ); } } - @SuppressWarnings ("unchecked") - public static Map optTableField(@Nonnull Map table, @Nonnull String key, Map def) throws LuaException { - Object value = table.get(key); - if (value == null) { + @SuppressWarnings( "unchecked" ) + public static Map optTableField( @Nonnull Map table, @Nonnull String key, Map def ) throws LuaException + { + Object value = table.get( key ); + if( value == null ) + { return def; - } else if (value instanceof Map) { + } + else if( value instanceof Map ) + { return (Map) value; - } else { - throw badKey(key, "table", value); + } + else + { + throw badKey( key, "table", value ); } } } diff --git a/src/main/java/dan200/computercraft/core/apis/TermAPI.java b/src/main/java/dan200/computercraft/core/apis/TermAPI.java index 41d7d435e..b081e2ee9 100644 --- a/src/main/java/dan200/computercraft/core/apis/TermAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/TermAPI.java @@ -6,8 +6,6 @@ package dan200.computercraft.core.apis; -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.ILuaAPI; import dan200.computercraft.api.lua.LuaException; @@ -16,23 +14,28 @@ import dan200.computercraft.core.computer.IComputerEnvironment; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.util.Colour; +import javax.annotation.Nonnull; + /** * The Terminal API provides functions for writing text to the terminal and monitors, and drawing ASCII graphics. * * @cc.module term */ -public class TermAPI extends TermMethods implements ILuaAPI { +public class TermAPI extends TermMethods implements ILuaAPI +{ private final Terminal terminal; private final IComputerEnvironment environment; - public TermAPI(IAPIEnvironment environment) { + public TermAPI( IAPIEnvironment environment ) + { this.terminal = environment.getTerminal(); this.environment = environment.getComputerEnvironment(); } @Override - public String[] getNames() { - return new String[] {"term"}; + public String[] getNames() + { + return new String[] { "term" }; } /** @@ -46,18 +49,20 @@ public class TermAPI extends TermMethods implements ILuaAPI { * @cc.treturn number The blue channel, will be between 0 and 1. * @see TermMethods#setPaletteColour(IArguments) To change the palette colour. */ - @LuaFunction ({ + @LuaFunction( { "nativePaletteColour", "nativePaletteColor" - }) - public final Object[] nativePaletteColour(int colour) throws LuaException { - int actualColour = 15 - parseColour(colour); - Colour c = Colour.fromInt(actualColour); + } ) + public final Object[] nativePaletteColour( int colour ) throws LuaException + { + int actualColour = 15 - parseColour( colour ); + Colour c = Colour.fromInt( actualColour ); float[] rgb = c.getRGB(); Object[] rgbObj = new Object[rgb.length]; - for (int i = 0; i < rgbObj.length; ++i) { + for( int i = 0; i < rgbObj.length; ++i ) + { rgbObj[i] = rgb[i]; } return rgbObj; @@ -65,12 +70,14 @@ public class TermAPI extends TermMethods implements ILuaAPI { @Nonnull @Override - public Terminal getTerminal() { + public Terminal getTerminal() + { return this.terminal; } @Override - public boolean isColour() { + public boolean isColour() + { return this.environment.isColour(); } } diff --git a/src/main/java/dan200/computercraft/core/apis/TermMethods.java b/src/main/java/dan200/computercraft/core/apis/TermMethods.java index da0fd371f..a3d959844 100644 --- a/src/main/java/dan200/computercraft/core/apis/TermMethods.java +++ b/src/main/java/dan200/computercraft/core/apis/TermMethods.java @@ -5,8 +5,6 @@ */ package dan200.computercraft.core.apis; -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; @@ -15,12 +13,15 @@ import dan200.computercraft.shared.util.Palette; import dan200.computercraft.shared.util.StringUtil; import org.apache.commons.lang3.ArrayUtils; +import javax.annotation.Nonnull; + /** * A base class for all objects which interact with a terminal. Namely the {@link TermAPI} and monitors. * * @cc.module term.Redirect */ -public abstract class TermMethods { +public abstract class TermMethods +{ /** * Write {@code text} at the current cursor position, moving the cursor to the end of the text. * @@ -31,12 +32,14 @@ public abstract class TermMethods { * @cc.param text The text to write. */ @LuaFunction - public final void write(IArguments arguments) throws LuaException { - String text = StringUtil.toString(arguments.get(0)); + public final void write( IArguments arguments ) throws LuaException + { + String text = StringUtil.toString( arguments.get( 0 ) ); Terminal terminal = this.getTerminal(); - synchronized (terminal) { - terminal.write(text); - terminal.setCursorPos(terminal.getCursorX() + text.length(), terminal.getCursorY()); + synchronized( terminal ) + { + terminal.write( text ); + terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() ); } } @@ -53,8 +56,9 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. */ @LuaFunction - public final void scroll(int y) throws LuaException { - this.getTerminal().scroll(y); + public final void scroll( int y ) throws LuaException + { + this.getTerminal().scroll( y ); } /** @@ -66,7 +70,8 @@ public abstract class TermMethods { * @cc.treturn number The y position of the cursor. */ @LuaFunction - public final Object[] getCursorPos() throws LuaException { + public final Object[] getCursorPos() throws LuaException + { Terminal terminal = this.getTerminal(); return new Object[] { terminal.getCursorX() + 1, @@ -82,10 +87,12 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. */ @LuaFunction - public final void setCursorPos(int x, int y) throws LuaException { + public final void setCursorPos( int x, int y ) throws LuaException + { Terminal terminal = this.getTerminal(); - synchronized (terminal) { - terminal.setCursorPos(x - 1, y - 1); + synchronized( terminal ) + { + terminal.setCursorPos( x - 1, y - 1 ); } } @@ -96,7 +103,8 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. */ @LuaFunction - public final boolean getCursorBlink() throws LuaException { + public final boolean getCursorBlink() throws LuaException + { return this.getTerminal().getCursorBlink(); } @@ -107,10 +115,12 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. */ @LuaFunction - public final void setCursorBlink(boolean blink) throws LuaException { + public final void setCursorBlink( boolean blink ) throws LuaException + { Terminal terminal = this.getTerminal(); - synchronized (terminal) { - terminal.setCursorBlink(blink); + synchronized( terminal ) + { + terminal.setCursorBlink( blink ); } } @@ -123,7 +133,8 @@ public abstract class TermMethods { * @cc.treturn number The terminal's height. */ @LuaFunction - public final Object[] getSize() throws LuaException { + public final Object[] getSize() throws LuaException + { Terminal terminal = this.getTerminal(); return new Object[] { terminal.getWidth(), @@ -137,7 +148,8 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. */ @LuaFunction - public final void clear() throws LuaException { + public final void clear() throws LuaException + { this.getTerminal().clear(); } @@ -147,7 +159,8 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. */ @LuaFunction - public final void clearLine() throws LuaException { + public final void clearLine() throws LuaException + { this.getTerminal().clearLine(); } @@ -158,12 +171,13 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants, returned by this function. */ - @LuaFunction ({ + @LuaFunction( { "getTextColour", "getTextColor" - }) - public final int getTextColour() throws LuaException { - return encodeColour(this.getTerminal().getTextColour()); + } ) + public final int getTextColour() throws LuaException + { + return encodeColour( this.getTerminal().getTextColour() ); } /** @@ -173,39 +187,47 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants. */ - @LuaFunction ({ + @LuaFunction( { "setTextColour", "setTextColor" - }) - public final void setTextColour(int colourArg) throws LuaException { - int colour = parseColour(colourArg); + } ) + public final void setTextColour( int colourArg ) throws LuaException + { + int colour = parseColour( colourArg ); Terminal terminal = this.getTerminal(); - synchronized (terminal) { - terminal.setTextColour(colour); + synchronized( terminal ) + { + terminal.setTextColour( colour ); } } - public static int parseColour(int colour) throws LuaException { - if (colour <= 0) { - throw new LuaException("Colour out of range"); + public static int parseColour( int colour ) throws LuaException + { + if( colour <= 0 ) + { + throw new LuaException( "Colour out of range" ); } - colour = getHighestBit(colour) - 1; - if (colour < 0 || colour > 15) { - throw new LuaException("Colour out of range"); + colour = getHighestBit( colour ) - 1; + if( colour < 0 || colour > 15 ) + { + throw new LuaException( "Colour out of range" ); } return colour; } - private static int getHighestBit(int group) { + private static int getHighestBit( int group ) + { int bit = 0; - while (group > 0) { + while( group > 0 ) + { group >>= 1; bit++; } return bit; } - public static int encodeColour(int colour) { + public static int encodeColour( int colour ) + { return 1 << colour; } @@ -216,12 +238,13 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants, returned by this function. */ - @LuaFunction ({ + @LuaFunction( { "getBackgroundColour", "getBackgroundColor" - }) - public final int getBackgroundColour() throws LuaException { - return encodeColour(this.getTerminal().getBackgroundColour()); + } ) + public final int getBackgroundColour() throws LuaException + { + return encodeColour( this.getTerminal().getBackgroundColour() ); } /** @@ -231,15 +254,17 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants. */ - @LuaFunction ({ + @LuaFunction( { "setBackgroundColour", "setBackgroundColor" - }) - public final void setBackgroundColour(int colourArg) throws LuaException { - int colour = parseColour(colourArg); + } ) + public final void setBackgroundColour( int colourArg ) throws LuaException + { + int colour = parseColour( colourArg ); Terminal terminal = this.getTerminal(); - synchronized (terminal) { - terminal.setBackgroundColour(colour); + synchronized( terminal ) + { + terminal.setBackgroundColour( colour ); } } @@ -251,11 +276,12 @@ public abstract class TermMethods { * @return Whether this terminal supports colour. * @throws LuaException (hidden) If the terminal cannot be found. */ - @LuaFunction ({ + @LuaFunction( { "isColour", "isColor" - }) - public final boolean getIsColour() throws LuaException { + } ) + public final boolean getIsColour() throws LuaException + { return this.isColour(); } @@ -269,26 +295,29 @@ public abstract class TermMethods { * {@code textColour} and {@code backgroundColour} must both be strings the same length as {@code text}. All characters represent a single hexadecimal * digit, which is converted to one of CC's colours. For instance, {@code "a"} corresponds to purple. * - * @param text The text to write. - * @param textColour The corresponding text colours. + * @param text The text to write. + * @param textColour The corresponding text colours. * @param backgroundColour The corresponding background colours. * @throws LuaException If the three inputs are not the same length. * @cc.see colors For a list of colour constants, and their hexadecimal values. * @cc.usage Prints "Hello, world!" in rainbow text. - *
{@code
+     * 
{@code
      *     term.blit("Hello, world!","01234456789ab","0000000000000")
      *     }
*/ @LuaFunction - public final void blit(String text, String textColour, String backgroundColour) throws LuaException { - if (textColour.length() != text.length() || backgroundColour.length() != text.length()) { - throw new LuaException("Arguments must be the same length"); + public final void blit( String text, String textColour, String backgroundColour ) throws LuaException + { + if( textColour.length() != text.length() || backgroundColour.length() != text.length() ) + { + throw new LuaException( "Arguments must be the same length" ); } Terminal terminal = this.getTerminal(); - synchronized (terminal) { - terminal.blit(text, textColour, backgroundColour); - terminal.setCursorPos(terminal.getCursorX() + text.length(), terminal.getCursorY()); + synchronized( terminal ) + { + terminal.blit( text, textColour, backgroundColour ); + terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() ); } } @@ -303,19 +332,19 @@ public abstract class TermMethods { * @throws LuaException (hidden) If the terminal cannot be found. * @cc.tparam [1] number index The colour whose palette should be changed. * @cc.tparam number colour A 24-bit integer representing the RGB value of the colour. For instance the integer `0xFF0000` corresponds to the colour - * #FF0000. + * #FF0000. * @cc.tparam [2] number index The colour whose palette should be changed. * @cc.tparam number r The intensity of the red channel, between 0 and 1. * @cc.tparam number g The intensity of the green channel, between 0 and 1. * @cc.tparam number b The intensity of the blue channel, between 0 and 1. * @cc.usage Change the @{colors.red|red colour} from the default #CC4C4C to #FF0000. - *
{@code
+     * 
{@code
      *     term.setPaletteColour(colors.red, 0xFF0000)
      *     term.setTextColour(colors.red)
      *     print("Hello, world!")
      *     }
* @cc.usage As above, but specifying each colour channel separately. - *
{@code
+     * 
{@code
      *     term.setPaletteColour(colors.red, 1, 0, 0)
      *     term.setTextColour(colors.red)
      *     print("Hello, world!")
@@ -323,27 +352,32 @@ public abstract class TermMethods {
      * @cc.see colors.unpackRGB To convert from the 24-bit format to three separate channels.
      * @cc.see colors.packRGB To convert from three separate channels to the 24-bit format.
      */
-    @LuaFunction ({
+    @LuaFunction( {
         "setPaletteColour",
         "setPaletteColor"
-    })
-    public final void setPaletteColour(IArguments args) throws LuaException {
-        int colour = 15 - parseColour(args.getInt(0));
-        if (args.count() == 2) {
-            int hex = args.getInt(1);
-            double[] rgb = Palette.decodeRGB8(hex);
-            setColour(this.getTerminal(), colour, rgb[0], rgb[1], rgb[2]);
-        } else {
-            double r = args.getFiniteDouble(1);
-            double g = args.getFiniteDouble(2);
-            double b = args.getFiniteDouble(3);
-            setColour(this.getTerminal(), colour, r, g, b);
+    } )
+    public final void setPaletteColour( IArguments args ) throws LuaException
+    {
+        int colour = 15 - parseColour( args.getInt( 0 ) );
+        if( args.count() == 2 )
+        {
+            int hex = args.getInt( 1 );
+            double[] rgb = Palette.decodeRGB8( hex );
+            setColour( this.getTerminal(), colour, rgb[0], rgb[1], rgb[2] );
+        }
+        else
+        {
+            double r = args.getFiniteDouble( 1 );
+            double g = args.getFiniteDouble( 2 );
+            double b = args.getFiniteDouble( 3 );
+            setColour( this.getTerminal(), colour, r, g, b );
         }
     }
 
-    public static void setColour(Terminal terminal, int colour, double r, double g, double b) {
+    public static void setColour( Terminal terminal, int colour, double r, double g, double b )
+    {
         terminal.getPalette()
-                .setColour(colour, r, g, b);
+            .setColour( colour, r, g, b );
         terminal.setChanged();
     }
 
@@ -357,16 +391,18 @@ public abstract class TermMethods {
      * @cc.treturn number The green channel, will be between 0 and 1.
      * @cc.treturn number The blue channel, will be between 0 and 1.
      */
-    @LuaFunction ({
+    @LuaFunction( {
         "getPaletteColour",
         "getPaletteColor"
-    })
-    public final Object[] getPaletteColour(int colourArg) throws LuaException {
-        int colour = 15 - parseColour(colourArg);
+    } )
+    public final Object[] getPaletteColour( int colourArg ) throws LuaException
+    {
+        int colour = 15 - parseColour( colourArg );
         Terminal terminal = this.getTerminal();
-        synchronized (terminal) {
-            return ArrayUtils.toObject(terminal.getPalette()
-                                               .getColour(colour));
+        synchronized( terminal )
+        {
+            return ArrayUtils.toObject( terminal.getPalette()
+                .getColour( colour ) );
         }
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java b/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java
index a2f9bb241..e1c9ddec7 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java
@@ -6,62 +6,74 @@
 
 package dan200.computercraft.core.apis.http;
 
+import dan200.computercraft.core.apis.IAPIEnvironment;
+
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.util.concurrent.Future;
 
-import dan200.computercraft.core.apis.IAPIEnvironment;
-
 /**
  * Checks a URL using {@link NetworkUtils#getAddress(String, int, boolean)}}
  *
  * This requires a DNS lookup, and so needs to occur off-thread.
  */
-public class CheckUrl extends Resource {
+public class CheckUrl extends Resource
+{
     private static final String EVENT = "http_check";
     private final IAPIEnvironment environment;
     private final String address;
     private final URI uri;
     private Future future;
 
-    public CheckUrl(ResourceGroup limiter, IAPIEnvironment environment, String address, URI uri) {
-        super(limiter);
+    public CheckUrl( ResourceGroup limiter, IAPIEnvironment environment, String address, URI uri )
+    {
+        super( limiter );
         this.environment = environment;
         this.address = address;
         this.uri = uri;
     }
 
-    public void run() {
-        if (this.isClosed()) {
+    public void run()
+    {
+        if( this.isClosed() )
+        {
             return;
         }
-        this.future = NetworkUtils.EXECUTOR.submit(this::doRun);
+        this.future = NetworkUtils.EXECUTOR.submit( this::doRun );
         this.checkClosed();
     }
 
-    private void doRun() {
-        if (this.isClosed()) {
+    private void doRun()
+    {
+        if( this.isClosed() )
+        {
             return;
         }
 
-        try {
+        try
+        {
             boolean ssl = uri.getScheme().equalsIgnoreCase( "https" );
             InetSocketAddress netAddress = NetworkUtils.getAddress( uri, ssl );
             NetworkUtils.getOptions( uri.getHost(), netAddress );
 
-            if (this.tryClose()) {
-                this.environment.queueEvent(EVENT, this.address, true);
+            if( this.tryClose() )
+            {
+                this.environment.queueEvent( EVENT, this.address, true );
             }
-        } catch (HTTPRequestException e) {
-            if (this.tryClose()) {
-                this.environment.queueEvent(EVENT, this.address, false, e.getMessage());
+        }
+        catch( HTTPRequestException e )
+        {
+            if( this.tryClose() )
+            {
+                this.environment.queueEvent( EVENT, this.address, false, e.getMessage() );
             }
         }
     }
 
     @Override
-    protected void dispose() {
+    protected void dispose()
+    {
         super.dispose();
-        this.future = closeFuture(this.future);
+        this.future = closeFuture( this.future );
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java b/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java
index beca1f0c6..ea1864ab6 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java
@@ -6,15 +6,18 @@
 
 package dan200.computercraft.core.apis.http;
 
-public class HTTPRequestException extends Exception {
+public class HTTPRequestException extends Exception
+{
     private static final long serialVersionUID = 7591208619422744652L;
 
-    public HTTPRequestException(String s) {
-        super(s);
+    public HTTPRequestException( String s )
+    {
+        super( s );
     }
 
     @Override
-    public Throwable fillInStackTrace() {
+    public Throwable fillInStackTrace()
+    {
         return this;
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java b/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java
index 76ddc19e8..4e2539aeb 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java
@@ -6,17 +6,6 @@
 
 package dan200.computercraft.core.apis.http;
 
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.security.KeyStore;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import javax.net.ssl.SSLException;
-import javax.net.ssl.TrustManagerFactory;
-
 import dan200.computercraft.ComputerCraft;
 import dan200.computercraft.core.apis.http.options.Action;
 import dan200.computercraft.core.apis.http.options.AddressRule;
@@ -28,67 +17,94 @@ import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.handler.ssl.SslContext;
 import io.netty.handler.ssl.SslContextBuilder;
 
+import javax.net.ssl.SSLException;
+import javax.net.ssl.TrustManagerFactory;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.security.KeyStore;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Just a shared object for executing simple HTTP related tasks.
  */
-public final class NetworkUtils {
-    public static final ExecutorService EXECUTOR = new ThreadPoolExecutor(4,
-                                                                          Integer.MAX_VALUE,
-                                                                          60L,
-                                                                          TimeUnit.SECONDS,
-                                                                          new SynchronousQueue<>(),
-                                                                          ThreadUtils.builder("Network")
-                                                                                     .setPriority(Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2)
-                                                                                     .build());
+public final class NetworkUtils
+{
+    public static final ExecutorService EXECUTOR = new ThreadPoolExecutor( 4,
+        Integer.MAX_VALUE,
+        60L,
+        TimeUnit.SECONDS,
+        new SynchronousQueue<>(),
+        ThreadUtils.builder( "Network" )
+            .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 )
+            .build() );
 
-    public static final EventLoopGroup LOOP_GROUP = new NioEventLoopGroup(4,
-                                                                          ThreadUtils.builder("Netty")
-                                                                                     .setPriority(Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2)
-                                                                                     .build());
+    public static final EventLoopGroup LOOP_GROUP = new NioEventLoopGroup( 4,
+        ThreadUtils.builder( "Netty" )
+            .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 )
+            .build() );
     private static final Object sslLock = new Object();
     private static TrustManagerFactory trustManager;
     private static SslContext sslContext;
     private static boolean triedSslContext = false;
-    private NetworkUtils() {
+
+    private NetworkUtils()
+    {
     }
 
-    public static SslContext getSslContext() throws HTTPRequestException {
-        if (sslContext != null || triedSslContext) {
+    public static SslContext getSslContext() throws HTTPRequestException
+    {
+        if( sslContext != null || triedSslContext )
+        {
             return sslContext;
         }
-        synchronized (sslLock) {
-            if (sslContext != null || triedSslContext) {
+        synchronized( sslLock )
+        {
+            if( sslContext != null || triedSslContext )
+            {
                 return sslContext;
             }
-            try {
+            try
+            {
                 return sslContext = SslContextBuilder.forClient()
-                                                     .trustManager(getTrustManager())
-                                                     .build();
-            } catch (SSLException e) {
-                ComputerCraft.log.error("Cannot construct SSL context", e);
+                    .trustManager( getTrustManager() )
+                    .build();
+            }
+            catch( SSLException e )
+            {
+                ComputerCraft.log.error( "Cannot construct SSL context", e );
                 triedSslContext = true;
                 sslContext = null;
 
-                throw new HTTPRequestException("Cannot create a secure connection");
+                throw new HTTPRequestException( "Cannot create a secure connection" );
             }
         }
     }
 
-    private static TrustManagerFactory getTrustManager() {
-        if (trustManager != null) {
+    private static TrustManagerFactory getTrustManager()
+    {
+        if( trustManager != null )
+        {
             return trustManager;
         }
-        synchronized (sslLock) {
-            if (trustManager != null) {
+        synchronized( sslLock )
+        {
+            if( trustManager != null )
+            {
                 return trustManager;
             }
 
             TrustManagerFactory tmf = null;
-            try {
-                tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-                tmf.init((KeyStore) null);
-            } catch (Exception e) {
-                ComputerCraft.log.error("Cannot setup trust manager", e);
+            try
+            {
+                tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
+                tmf.init( (KeyStore) null );
+            }
+            catch( Exception e )
+            {
+                ComputerCraft.log.error( "Cannot setup trust manager", e );
             }
 
             return trustManager = tmf;
@@ -117,17 +133,20 @@ public final class NetworkUtils {
      *
      * @param host The host to resolve.
      * @param port The port, or -1 if not defined.
-     * @param ssl Whether to connect with SSL. This is used to find the default port if not otherwise specified.
+     * @param ssl  Whether to connect with SSL. This is used to find the default port if not otherwise specified.
      * @return The resolved address.
      * @throws HTTPRequestException If the host is not malformed.
      */
-    public static InetSocketAddress getAddress(String host, int port, boolean ssl) throws HTTPRequestException {
-        if (port < 0) {
+    public static InetSocketAddress getAddress( String host, int port, boolean ssl ) throws HTTPRequestException
+    {
+        if( port < 0 )
+        {
             port = ssl ? 443 : 80;
         }
-        InetSocketAddress socketAddress = new InetSocketAddress(host, port);
-        if (socketAddress.isUnresolved()) {
-            throw new HTTPRequestException("Unknown host");
+        InetSocketAddress socketAddress = new InetSocketAddress( host, port );
+        if( socketAddress.isUnresolved() )
+        {
+            throw new HTTPRequestException( "Unknown host" );
         }
         return socketAddress;
     }
@@ -135,15 +154,17 @@ public final class NetworkUtils {
     /**
      * Get options for a specific domain.
      *
-     * @param host The host to resolve.
+     * @param host    The host to resolve.
      * @param address The address, resolved by {@link #getAddress(String, int, boolean)}.
      * @return The options for this host.
      * @throws HTTPRequestException If the host is not permitted
      */
-    public static Options getOptions(String host, InetSocketAddress address) throws HTTPRequestException {
+    public static Options getOptions( String host, InetSocketAddress address ) throws HTTPRequestException
+    {
         Options options = AddressRule.apply( ComputerCraft.httpRules, host, address );
-        if (options.action == Action.DENY) {
-            throw new HTTPRequestException("Domain not permitted");
+        if( options.action == Action.DENY )
+        {
+            throw new HTTPRequestException( "Domain not permitted" );
         }
         return options;
     }
@@ -154,9 +175,10 @@ public final class NetworkUtils {
      * @param buffer The buffer to read.
      * @return The resulting bytes.
      */
-    public static byte[] toBytes(ByteBuf buffer) {
+    public static byte[] toBytes( ByteBuf buffer )
+    {
         byte[] bytes = new byte[buffer.readableBytes()];
-        buffer.readBytes(bytes);
+        buffer.readBytes( bytes );
         return bytes;
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/Resource.java b/src/main/java/dan200/computercraft/core/apis/http/Resource.java
index cc2981402..1c16cc050 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/Resource.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/Resource.java
@@ -6,6 +6,10 @@
 
 package dan200.computercraft.core.apis.http;
 
+import dan200.computercraft.shared.util.IoUtil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+
 import java.io.Closeable;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
@@ -14,34 +18,36 @@ import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
 
-import dan200.computercraft.shared.util.IoUtil;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-
 /**
  * A holder for one or more resources, with a lifetime.
  *
  * @param  The type of this resource. Should be the class extending from {@link Resource}.
  */
-public abstract class Resource> implements Closeable {
+public abstract class Resource> implements Closeable
+{
     private static final ReferenceQueue QUEUE = new ReferenceQueue<>();
-    private final AtomicBoolean closed = new AtomicBoolean(false);
+    private final AtomicBoolean closed = new AtomicBoolean( false );
     private final ResourceGroup limiter;
 
-    protected Resource(ResourceGroup limiter) {
+    protected Resource( ResourceGroup limiter )
+    {
         this.limiter = limiter;
     }
 
-    protected static  T closeCloseable(T closeable) {
-        IoUtil.closeQuietly(closeable);
+    protected static  T closeCloseable( T closeable )
+    {
+        IoUtil.closeQuietly( closeable );
         return null;
     }
 
-    protected static ChannelFuture closeChannel(ChannelFuture future) {
-        if (future != null) {
-            future.cancel(false);
+    protected static ChannelFuture closeChannel( ChannelFuture future )
+    {
+        if( future != null )
+        {
+            future.cancel( false );
             Channel channel = future.channel();
-            if (channel != null && channel.isOpen()) {
+            if( channel != null && channel.isOpen() )
+            {
                 channel.close();
             }
         }
@@ -49,22 +55,27 @@ public abstract class Resource> implements Closeable {
         return null;
     }
 
-    protected static > T closeFuture(T future) {
-        if (future != null) {
-            future.cancel(true);
+    protected static > T closeFuture( T future )
+    {
+        if( future != null )
+        {
+            future.cancel( true );
         }
         return null;
     }
 
-    public static void cleanup() {
+    public static void cleanup()
+    {
         Reference reference;
-        while ((reference = QUEUE.poll()) != null) {
+        while( (reference = QUEUE.poll()) != null )
+        {
             ((CloseReference) reference).resource.close();
         }
     }
 
     @Override
-    public final void close() {
+    public final void close()
+    {
         this.tryClose();
     }
 
@@ -73,8 +84,10 @@ public abstract class Resource> implements Closeable {
      *
      * @return Whether this was successfully closed, or {@code false} if it has already been closed.
      */
-    protected final boolean tryClose() {
-        if (this.closed.getAndSet(true)) {
+    protected final boolean tryClose()
+    {
+        if( this.closed.getAndSet( true ) )
+        {
             return false;
         }
         this.dispose();
@@ -86,7 +99,8 @@ public abstract class Resource> implements Closeable {
      *
      * @return Whether this resource is closed.
      */
-    public final boolean isClosed() {
+    public final boolean isClosed()
+    {
         return this.closed.get();
     }
 
@@ -95,8 +109,10 @@ public abstract class Resource> implements Closeable {
      *
      * @return Whether this resource has been closed.
      */
-    public final boolean checkClosed() {
-        if (!this.closed.get()) {
+    public final boolean checkClosed()
+    {
+        if( !this.closed.get() )
+        {
             return false;
         }
         this.dispose();
@@ -108,34 +124,39 @@ public abstract class Resource> implements Closeable {
      *
      * Note, this may be called multiple times, and so should be thread-safe and avoid any major side effects.
      */
-    protected void dispose() {
-        @SuppressWarnings ("unchecked")
+    protected void dispose()
+    {
+        @SuppressWarnings( "unchecked" )
         T thisT = (T) this;
-        this.limiter.release(thisT);
+        this.limiter.release( thisT );
     }
 
     /**
      * Create a {@link WeakReference} which will close {@code this} when collected.
      *
-     * @param  The object we are wrapping in a reference.
+     * @param     The object we are wrapping in a reference.
      * @param object The object to reference to
      * @return The weak reference.
      */
-    protected  WeakReference createOwnerReference(R object) {
-        return new CloseReference<>(this, object);
+    protected  WeakReference createOwnerReference( R object )
+    {
+        return new CloseReference<>( this, object );
     }
 
-    public boolean queue(Consumer task) {
-        @SuppressWarnings ("unchecked")
+    public boolean queue( Consumer task )
+    {
+        @SuppressWarnings( "unchecked" )
         T thisT = (T) this;
-        return this.limiter.queue(thisT, () -> task.accept(thisT));
+        return this.limiter.queue( thisT, () -> task.accept( thisT ) );
     }
 
-    private static class CloseReference extends WeakReference {
+    private static class CloseReference extends WeakReference
+    {
         final Resource resource;
 
-        CloseReference(Resource resource, T referent) {
-            super(referent, QUEUE);
+        CloseReference( Resource resource, T referent )
+        {
+            super( referent, QUEUE );
             this.resource = resource;
         }
     }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java b/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java
index 4510a6e98..058c9875f 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java
@@ -17,29 +17,35 @@ import java.util.function.Supplier;
  *
  * @param  The type of the resource this group manages.
  */
-public class ResourceGroup> {
+public class ResourceGroup>
+{
     private static final IntSupplier ZERO = () -> 0;
 
     final IntSupplier limit;
-    final Set resources = Collections.newSetFromMap(new ConcurrentHashMap<>());
+    final Set resources = Collections.newSetFromMap( new ConcurrentHashMap<>() );
     boolean active = false;
 
-    public ResourceGroup(IntSupplier limit) {
+    public ResourceGroup( IntSupplier limit )
+    {
         this.limit = limit;
     }
 
-    public ResourceGroup() {
+    public ResourceGroup()
+    {
         this.limit = ZERO;
     }
 
-    public void startup() {
+    public void startup()
+    {
         this.active = true;
     }
 
-    public synchronized void shutdown() {
+    public synchronized void shutdown()
+    {
         this.active = false;
 
-        for (T resource : this.resources) {
+        for( T resource : this.resources )
+        {
             resource.close();
         }
         this.resources.clear();
@@ -48,29 +54,34 @@ public class ResourceGroup> {
     }
 
 
-    public final boolean queue(T resource, Runnable setup) {
-        return this.queue(() -> {
+    public final boolean queue( T resource, Runnable setup )
+    {
+        return this.queue( () -> {
             setup.run();
             return resource;
-        });
+        } );
     }
 
-    public synchronized boolean queue(Supplier resource) {
+    public synchronized boolean queue( Supplier resource )
+    {
         Resource.cleanup();
-        if (!this.active) {
+        if( !this.active )
+        {
             return false;
         }
 
         int limit = this.limit.getAsInt();
-        if (limit <= 0 || this.resources.size() < limit) {
-            this.resources.add(resource.get());
+        if( limit <= 0 || this.resources.size() < limit )
+        {
+            this.resources.add( resource.get() );
             return true;
         }
 
         return false;
     }
 
-    public synchronized void release(T resource) {
-        this.resources.remove(resource);
+    public synchronized void release( T resource )
+    {
+        this.resources.remove( resource );
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java b/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java
index 080a3a54a..74c79ce53 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java
@@ -15,47 +15,58 @@ import java.util.function.Supplier;
  *
  * @param  The type of the resource this queue manages.
  */
-public class ResourceQueue> extends ResourceGroup {
+public class ResourceQueue> extends ResourceGroup
+{
     private final ArrayDeque> pending = new ArrayDeque<>();
 
-    public ResourceQueue(IntSupplier limit) {
-        super(limit);
+    public ResourceQueue( IntSupplier limit )
+    {
+        super( limit );
     }
 
-    public ResourceQueue() {
+    public ResourceQueue()
+    {
     }
 
     @Override
-    public synchronized void shutdown() {
+    public synchronized void shutdown()
+    {
         super.shutdown();
         this.pending.clear();
     }
 
     @Override
-    public synchronized boolean queue(Supplier resource) {
-        if (!this.active) {
+    public synchronized boolean queue( Supplier resource )
+    {
+        if( !this.active )
+        {
             return false;
         }
 
-        if (!super.queue(resource)) {
-            this.pending.add(resource);
+        if( !super.queue( resource ) )
+        {
+            this.pending.add( resource );
         }
         return true;
     }
 
     @Override
-    public synchronized void release(T resource) {
-        super.release(resource);
+    public synchronized void release( T resource )
+    {
+        super.release( resource );
 
-        if (!this.active) {
+        if( !this.active )
+        {
             return;
         }
 
         int limit = this.limit.getAsInt();
-        if (limit <= 0 || this.resources.size() < limit) {
+        if( limit <= 0 || this.resources.size() < limit )
+        {
             Supplier next = this.pending.poll();
-            if (next != null) {
-                this.resources.add(next.get());
+            if( next != null )
+            {
+                this.resources.add( next.get() );
             }
         }
     }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/Action.java b/src/main/java/dan200/computercraft/core/apis/http/options/Action.java
index 6410fc2d9..df8641a2f 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/options/Action.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/options/Action.java
@@ -7,13 +7,15 @@ package dan200.computercraft.core.apis.http.options;
 
 import javax.annotation.Nonnull;
 
-public enum Action {
+public enum Action
+{
     ALLOW, DENY;
 
-    private final PartialOptions partial = new PartialOptions(this, null, null, null, null);
+    private final PartialOptions partial = new PartialOptions( this, null, null, null, null );
 
     @Nonnull
-    public PartialOptions toPartial() {
+    public PartialOptions toPartial()
+    {
         return this.partial;
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java
index e9b1b1d8f..912e8e057 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java
@@ -6,25 +6,24 @@
 
 package dan200.computercraft.core.apis.http.options;
 
+import com.google.common.net.InetAddresses;
+import dan200.computercraft.core.apis.http.options.AddressPredicate.DomainPattern;
+import dan200.computercraft.core.apis.http.options.AddressPredicate.HostRange;
+import dan200.computercraft.core.apis.http.options.AddressPredicate.PrivatePattern;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.regex.Pattern;
 
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.google.common.net.InetAddresses;
-
-import dan200.computercraft.core.apis.http.options.AddressPredicate.DomainPattern;
-import dan200.computercraft.core.apis.http.options.AddressPredicate.HostRange;
-import dan200.computercraft.core.apis.http.options.AddressPredicate.PrivatePattern;
-
 /**
  * A pattern which matches an address, and controls whether it is accessible or not.
  */
-public final class AddressRule {
+public final class AddressRule
+{
     public static final long MAX_DOWNLOAD = 16 * 1024 * 1024;
     public static final long MAX_UPLOAD = 4 * 1024 * 1024;
     public static final int TIMEOUT = 30_000;
@@ -33,31 +32,38 @@ public final class AddressRule {
     private final AddressPredicate predicate;
     private final Integer port;
     private final PartialOptions partial;
-    private AddressRule( @Nonnull AddressPredicate predicate, @Nullable Integer port, @Nonnull PartialOptions partial ) {
+
+    private AddressRule( @Nonnull AddressPredicate predicate, @Nullable Integer port, @Nonnull PartialOptions partial )
+    {
         this.predicate = predicate;
         this.partial = partial;
-		this.port = port;
+        this.port = port;
     }
 
     @Nullable
-    public static AddressRule parse( String filter, @Nullable Integer port, @Nonnull PartialOptions partial ) {
-        int cidr = filter.indexOf('/');
-        if (cidr >= 0) {
-            String addressStr = filter.substring(0, cidr);
-            String prefixSizeStr = filter.substring(cidr + 1);
+    public static AddressRule parse( String filter, @Nullable Integer port, @Nonnull PartialOptions partial )
+    {
+        int cidr = filter.indexOf( '/' );
+        if( cidr >= 0 )
+        {
+            String addressStr = filter.substring( 0, cidr );
+            String prefixSizeStr = filter.substring( cidr + 1 );
             HostRange range = HostRange.parse( addressStr, prefixSizeStr );
             return range == null ? null : new AddressRule( range, port, partial );
         }
         else if( filter.equalsIgnoreCase( "$private" ) )
         {
             return new AddressRule( PrivatePattern.INSTANCE, port, partial );
-        } else {
+        }
+        else
+        {
             Pattern pattern = Pattern.compile( "^\\Q" + filter.replaceAll( "\\*", "\\\\E.*\\\\Q" ) + "\\E$", Pattern.CASE_INSENSITIVE );
             return new AddressRule( new DomainPattern( pattern ), port, partial );
         }
     }
 
-    public static Options apply( Iterable rules, String domain, InetSocketAddress socketAddress ) {
+    public static Options apply( Iterable rules, String domain, InetSocketAddress socketAddress )
+    {
         PartialOptions options = null;
         boolean hasMany = false;
 
@@ -66,19 +72,24 @@ public final class AddressRule {
         Inet4Address ipv4Address = address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address )
             ? InetAddresses.get6to4IPv4Address( (Inet6Address) address ) : null;
 
-        for (AddressRule rule : rules) {
+        for( AddressRule rule : rules )
+        {
             if( !rule.matches( domain, port, address, ipv4Address ) ) continue;
 
-            if (options == null) {
+            if( options == null )
+            {
                 options = rule.partial;
-            } else {
+            }
+            else
+            {
 
-                if (!hasMany) {
+                if( !hasMany )
+                {
                     options = options.copy();
                     hasMany = true;
                 }
 
-                options.merge(rule.partial);
+                options.merge( rule.partial );
             }
         }
 
@@ -94,8 +105,9 @@ public final class AddressRule {
      * @param ipv4Address An ipv4 version of the address, if the original was an ipv6 address.
      * @return Whether it matches any of these patterns.
      */
-    private boolean matches(String domain, int port, InetAddress address, Inet4Address ipv4Address) {
-		if( this.port != null && this.port != port ) return false;
+    private boolean matches( String domain, int port, InetAddress address, Inet4Address ipv4Address )
+    {
+        if( this.port != null && this.port != port ) return false;
         return predicate.matches( domain )
             || predicate.matches( address )
             || (ipv4Address != null && predicate.matches( ipv4Address ));
diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java
index 660acfb18..3fb2c6e6f 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java
@@ -17,116 +17,117 @@ import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
 
-public class AddressRuleConfig {
+public class AddressRuleConfig
+{
 
-        public static UnmodifiableConfig makeRule( String host, Action action )
+    public static UnmodifiableConfig makeRule( String host, Action action )
+    {
+        CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new );
+        config.add( "host", host );
+        config.add( "action", action.name().toLowerCase( Locale.ROOT ) );
+
+        if( host.equals( "*" ) && action == Action.ALLOW )
         {
-            CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new );
-            config.add( "host", host );
-            config.add( "action", action.name().toLowerCase( Locale.ROOT ) );
+            config.setComment( "timeout", "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." );
+            config.add( "timeout", AddressRule.TIMEOUT );
 
-            if( host.equals( "*" ) && action == Action.ALLOW )
-            {
-                config.setComment( "timeout", "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." );
-                config.add( "timeout", AddressRule.TIMEOUT );
+            config.setComment( "max_download", "The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client." );
+            config.set( "max_download", AddressRule.MAX_DOWNLOAD );
 
-                config.setComment( "max_download", "The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client." );
-                config.set( "max_download", AddressRule.MAX_DOWNLOAD );
+            config.setComment( "max_upload", "The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text." );
+            config.set( "max_upload", AddressRule.MAX_UPLOAD );
 
-                config.setComment( "max_upload", "The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text." );
-                config.set( "max_upload", AddressRule.MAX_UPLOAD );
-
-                config.setComment( "max_websocket_message", "The maximum size (in bytes) that a computer can send or receive in one websocket packet." );
-                config.set( "max_websocket_message", AddressRule.WEBSOCKET_MESSAGE );
-            }
-
-            return config;
+            config.setComment( "max_websocket_message", "The maximum size (in bytes) that a computer can send or receive in one websocket packet." );
+            config.set( "max_websocket_message", AddressRule.WEBSOCKET_MESSAGE );
         }
 
-        public static boolean checkRule( UnmodifiableConfig builder )
+        return config;
+    }
+
+    public static boolean checkRule( UnmodifiableConfig builder )
+    {
+        String hostObj = get( builder, "host", String.class ).orElse( null );
+        Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
+        return hostObj != null && checkEnum( builder, "action", Action.class )
+            && check( builder, "port", Number.class )
+            && check( builder, "timeout", Number.class )
+            && check( builder, "max_upload", Number.class )
+            && check( builder, "max_download", Number.class )
+            && check( builder, "websocket_message", Number.class )
+            && AddressRule.parse( hostObj, port, PartialOptions.DEFAULT ) != null;
+    }
+
+    @Nullable
+    public static AddressRule parseRule( UnmodifiableConfig builder )
+    {
+        String hostObj = get( builder, "host", String.class ).orElse( null );
+        Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
+        if( hostObj == null ) return null;
+
+        Action action = getEnum( builder, "action", Action.class ).orElse( null );
+        Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null );
+        Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null );
+        Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null );
+        Integer websocketMessage = get( builder, "websocket_message", Number.class ).map( Number::intValue ).orElse( null );
+
+        PartialOptions options = new PartialOptions(
+            action,
+            maxUpload,
+            maxDownload,
+            timeout,
+            websocketMessage
+        );
+
+        return AddressRule.parse( hostObj, port, options );
+    }
+
+    private static  boolean check( UnmodifiableConfig config, String field, Class klass )
+    {
+        Object value = config.get( field );
+        if( value == null || klass.isInstance( value ) ) return true;
+
+        ComputerCraft.log.warn( "HTTP rule's {} is not a {}.", field, klass.getSimpleName() );
+        return false;
+    }
+
+    private static > boolean checkEnum( UnmodifiableConfig config, String field, Class klass )
+    {
+        Object value = config.get( field );
+        if( value == null ) return true;
+
+        if( !(value instanceof String) )
         {
-            String hostObj = get( builder, "host", String.class ).orElse( null );
-            Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
-            return hostObj != null && checkEnum( builder, "action", Action.class )
-                && check( builder, "port", Number.class )
-                && check( builder, "timeout", Number.class )
-                && check( builder, "max_upload", Number.class )
-                && check( builder, "max_download", Number.class )
-                && check( builder, "websocket_message", Number.class )
-                && AddressRule.parse( hostObj, port, PartialOptions.DEFAULT ) != null;
-        }
-
-        @Nullable
-        public static AddressRule parseRule( UnmodifiableConfig builder )
-        {
-            String hostObj = get( builder, "host", String.class ).orElse( null );
-            Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
-            if( hostObj == null ) return null;
-
-            Action action = getEnum( builder, "action", Action.class ).orElse( null );
-            Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null );
-            Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null );
-            Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null );
-            Integer websocketMessage = get( builder, "websocket_message", Number.class ).map( Number::intValue ).orElse( null );
-
-            PartialOptions options = new PartialOptions(
-                action,
-                maxUpload,
-                maxDownload,
-                timeout,
-                websocketMessage
-            );
-
-            return AddressRule.parse( hostObj, port, options );
-        }
-
-        private static  boolean check( UnmodifiableConfig config, String field, Class klass )
-        {
-            Object value = config.get( field );
-            if( value == null || klass.isInstance( value ) ) return true;
-
-            ComputerCraft.log.warn( "HTTP rule's {} is not a {}.", field, klass.getSimpleName() );
+            ComputerCraft.log.warn( "HTTP rule's {} is not a string", field );
             return false;
         }
 
-        private static > boolean checkEnum( UnmodifiableConfig config, String field, Class klass )
+        if( parseEnum( klass, (String) value ) == null )
         {
-            Object value = config.get( field );
-            if( value == null ) return true;
-
-            if( !(value instanceof String) )
-            {
-                ComputerCraft.log.warn( "HTTP rule's {} is not a string", field );
-                return false;
-            }
-
-            if( parseEnum( klass, (String) value ) == null )
-            {
-                ComputerCraft.log.warn( "HTTP rule's {} is not a known option", field );
-                return false;
-            }
-
-            return true;
+            ComputerCraft.log.warn( "HTTP rule's {} is not a known option", field );
+            return false;
         }
 
-        private static  Optional get( UnmodifiableConfig config, String field, Class klass )
-        {
-            Object value = config.get( field );
-            return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty();
-        }
+        return true;
+    }
 
-        private static > Optional getEnum( UnmodifiableConfig config, String field, Class klass )
-        {
-            return get( config, field, String.class ).map( x -> parseEnum( klass, x ) );
-        }
+    private static  Optional get( UnmodifiableConfig config, String field, Class klass )
+    {
+        Object value = config.get( field );
+        return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty();
+    }
 
-        @Nullable
-        private static > T parseEnum( Class klass, String x )
+    private static > Optional getEnum( UnmodifiableConfig config, String field, Class klass )
+    {
+        return get( config, field, String.class ).map( x -> parseEnum( klass, x ) );
+    }
+
+    @Nullable
+    private static > T parseEnum( Class klass, String x )
+    {
+        for( T value : klass.getEnumConstants() )
         {
-            for( T value : klass.getEnumConstants() )
-            {
-                if( value.name().equalsIgnoreCase( x ) ) return value;
-            }
-            return null;
+            if( value.name().equalsIgnoreCase( x ) ) return value;
         }
+        return null;
+    }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/Options.java b/src/main/java/dan200/computercraft/core/apis/http/options/Options.java
index d4fde11f6..d6074a9a4 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/options/Options.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/options/Options.java
@@ -10,14 +10,17 @@ import javax.annotation.Nonnull;
 /**
  * Options about a specific domain.
  */
-public final class Options {
-    @Nonnull public final Action action;
+public final class Options
+{
+    @Nonnull
+    public final Action action;
     public final long maxUpload;
     public final long maxDownload;
     public final int timeout;
     public final int websocketMessage;
 
-    Options(@Nonnull Action action, long maxUpload, long maxDownload, int timeout, int websocketMessage) {
+    Options( @Nonnull Action action, long maxUpload, long maxDownload, int timeout, int websocketMessage )
+    {
         this.action = action;
         this.maxUpload = maxUpload;
         this.maxDownload = maxDownload;
diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java b/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java
index 9835f461b..76699aa30 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java
@@ -7,8 +7,9 @@ package dan200.computercraft.core.apis.http.options;
 
 import javax.annotation.Nonnull;
 
-public final class PartialOptions {
-    static final PartialOptions DEFAULT = new PartialOptions(null, null, null, null, null);
+public final class PartialOptions
+{
+    static final PartialOptions DEFAULT = new PartialOptions( null, null, null, null, null );
 
     Action action;
     Long maxUpload;
@@ -18,7 +19,8 @@ public final class PartialOptions {
 
     Options options;
 
-    PartialOptions(Action action, Long maxUpload, Long maxDownload, Integer timeout, Integer websocketMessage) {
+    PartialOptions( Action action, Long maxUpload, Long maxDownload, Integer timeout, Integer websocketMessage )
+    {
         this.action = action;
         this.maxUpload = maxUpload;
         this.maxDownload = maxDownload;
@@ -27,36 +29,45 @@ public final class PartialOptions {
     }
 
     @Nonnull
-    Options toOptions() {
-        if (this.options != null) {
+    Options toOptions()
+    {
+        if( this.options != null )
+        {
             return this.options;
         }
 
-        return this.options = new Options(this.action == null ? Action.DENY : this.action,
-                                     this.maxUpload == null ? AddressRule.MAX_UPLOAD : this.maxUpload,
-                                     this.maxDownload == null ? AddressRule.MAX_DOWNLOAD : this.maxDownload,
-                                     this.timeout == null ? AddressRule.TIMEOUT : this.timeout, this.websocketMessage == null ? AddressRule.WEBSOCKET_MESSAGE : this.websocketMessage);
+        return this.options = new Options( this.action == null ? Action.DENY : this.action,
+            this.maxUpload == null ? AddressRule.MAX_UPLOAD : this.maxUpload,
+            this.maxDownload == null ? AddressRule.MAX_DOWNLOAD : this.maxDownload,
+            this.timeout == null ? AddressRule.TIMEOUT : this.timeout, this.websocketMessage == null ? AddressRule.WEBSOCKET_MESSAGE : this.websocketMessage );
     }
 
-    void merge(@Nonnull PartialOptions other) {
-        if (this.action == null && other.action != null) {
+    void merge( @Nonnull PartialOptions other )
+    {
+        if( this.action == null && other.action != null )
+        {
             this.action = other.action;
         }
-        if (this.maxUpload == null && other.maxUpload != null) {
+        if( this.maxUpload == null && other.maxUpload != null )
+        {
             this.maxUpload = other.maxUpload;
         }
-        if (this.maxDownload == null && other.maxDownload != null) {
+        if( this.maxDownload == null && other.maxDownload != null )
+        {
             this.maxDownload = other.maxDownload;
         }
-        if (this.timeout == null && other.timeout != null) {
+        if( this.timeout == null && other.timeout != null )
+        {
             this.timeout = other.timeout;
         }
-        if (this.websocketMessage == null && other.websocketMessage != null) {
+        if( this.websocketMessage == null && other.websocketMessage != null )
+        {
             this.websocketMessage = other.websocketMessage;
         }
     }
 
-    PartialOptions copy() {
-        return new PartialOptions(this.action, this.maxUpload, this.maxDownload, this.timeout, this.websocketMessage);
+    PartialOptions copy()
+    {
+        return new PartialOptions( this.action, this.maxUpload, this.maxDownload, this.timeout, this.websocketMessage );
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java
index dba5b0e7b..b6ba95a21 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java
@@ -6,16 +6,6 @@
 
 package dan200.computercraft.core.apis.http.request;
 
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
 import dan200.computercraft.ComputerCraft;
 import dan200.computercraft.core.apis.IAPIEnvironment;
 import dan200.computercraft.core.apis.http.HTTPRequestException;
@@ -34,19 +24,26 @@ import io.netty.channel.ConnectTimeoutException;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.channel.socket.nio.NioSocketChannel;
 import io.netty.handler.codec.TooLongFrameException;
-import io.netty.handler.codec.http.HttpClientCodec;
-import io.netty.handler.codec.http.HttpContentDecompressor;
-import io.netty.handler.codec.http.HttpHeaderNames;
-import io.netty.handler.codec.http.HttpHeaders;
-import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.*;
 import io.netty.handler.ssl.SslContext;
 import io.netty.handler.timeout.ReadTimeoutException;
 import io.netty.handler.timeout.ReadTimeoutHandler;
 
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * Represents an in-progress HTTP request.
  */
-public class HttpRequest extends Resource {
+public class HttpRequest extends Resource
+{
     private static final String SUCCESS_EVENT = "http_success";
     private static final String FAILURE_EVENT = "http_failure";
 
@@ -61,201 +58,252 @@ public class HttpRequest extends Resource {
     private ChannelFuture connectFuture;
     private HttpRequestHandler currentRequest;
 
-    public HttpRequest(ResourceGroup limiter, IAPIEnvironment environment, String address, String postText, HttpHeaders headers,
-                       boolean binary, boolean followRedirects) {
-        super(limiter);
+    public HttpRequest( ResourceGroup limiter, IAPIEnvironment environment, String address, String postText, HttpHeaders headers,
+                        boolean binary, boolean followRedirects )
+    {
+        super( limiter );
         this.environment = environment;
         this.address = address;
-        this.postBuffer = postText != null ? Unpooled.wrappedBuffer(postText.getBytes(StandardCharsets.UTF_8)) : Unpooled.buffer(0);
+        this.postBuffer = postText != null ? Unpooled.wrappedBuffer( postText.getBytes( StandardCharsets.UTF_8 ) ) : Unpooled.buffer( 0 );
         this.headers = headers;
         this.binary = binary;
-        this.redirects = new AtomicInteger(followRedirects ? MAX_REDIRECTS : 0);
+        this.redirects = new AtomicInteger( followRedirects ? MAX_REDIRECTS : 0 );
 
-        if (postText != null) {
-            if (!headers.contains(HttpHeaderNames.CONTENT_TYPE)) {
-                headers.set(HttpHeaderNames.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=utf-8");
+        if( postText != null )
+        {
+            if( !headers.contains( HttpHeaderNames.CONTENT_TYPE ) )
+            {
+                headers.set( HttpHeaderNames.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=utf-8" );
             }
 
-            if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) {
-                headers.set(HttpHeaderNames.CONTENT_LENGTH, this.postBuffer.readableBytes());
+            if( !headers.contains( HttpHeaderNames.CONTENT_LENGTH ) )
+            {
+                headers.set( HttpHeaderNames.CONTENT_LENGTH, this.postBuffer.readableBytes() );
             }
         }
     }
 
-    public static URI checkUri(String address) throws HTTPRequestException {
+    public static URI checkUri( String address ) throws HTTPRequestException
+    {
         URI url;
-        try {
-            url = new URI(address);
-        } catch (URISyntaxException e) {
-            throw new HTTPRequestException("URL malformed");
+        try
+        {
+            url = new URI( address );
+        }
+        catch( URISyntaxException e )
+        {
+            throw new HTTPRequestException( "URL malformed" );
         }
 
-        checkUri(url);
+        checkUri( url );
         return url;
     }
 
-    public static void checkUri(URI url) throws HTTPRequestException {
+    public static void checkUri( URI url ) throws HTTPRequestException
+    {
         // Validate the URL
-        if (url.getScheme() == null) {
-            throw new HTTPRequestException("Must specify http or https");
+        if( url.getScheme() == null )
+        {
+            throw new HTTPRequestException( "Must specify http or https" );
         }
-        if (url.getHost() == null) {
-            throw new HTTPRequestException("URL malformed");
+        if( url.getHost() == null )
+        {
+            throw new HTTPRequestException( "URL malformed" );
         }
 
         String scheme = url.getScheme()
-                           .toLowerCase(Locale.ROOT);
-        if (!scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")) {
-            throw new HTTPRequestException("Invalid protocol '" + scheme + "'");
+            .toLowerCase( Locale.ROOT );
+        if( !scheme.equalsIgnoreCase( "http" ) && !scheme.equalsIgnoreCase( "https" ) )
+        {
+            throw new HTTPRequestException( "Invalid protocol '" + scheme + "'" );
         }
     }
 
-    public IAPIEnvironment environment() {
+    public IAPIEnvironment environment()
+    {
         return this.environment;
     }
 
-    public void request(URI uri, HttpMethod method) {
-        if (this.isClosed()) {
+    public void request( URI uri, HttpMethod method )
+    {
+        if( this.isClosed() )
+        {
             return;
         }
-        this.executorFuture = NetworkUtils.EXECUTOR.submit(() -> this.doRequest(uri, method));
+        this.executorFuture = NetworkUtils.EXECUTOR.submit( () -> this.doRequest( uri, method ) );
         this.checkClosed();
     }
 
-    private void doRequest(URI uri, HttpMethod method) {
+    private void doRequest( URI uri, HttpMethod method )
+    {
         // If we're cancelled, abort.
-        if (this.isClosed()) {
+        if( this.isClosed() )
+        {
             return;
         }
 
-        try {
+        try
+        {
             boolean ssl = uri.getScheme()
-                             .equalsIgnoreCase("https");
-            InetSocketAddress socketAddress = NetworkUtils.getAddress(uri, ssl);
-            Options options = NetworkUtils.getOptions(uri.getHost(), socketAddress);
+                .equalsIgnoreCase( "https" );
+            InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl );
+            Options options = NetworkUtils.getOptions( uri.getHost(), socketAddress );
             SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null;
 
             // getAddress may have a slight delay, so let's perform another cancellation check.
-            if (this.isClosed()) {
+            if( this.isClosed() )
+            {
                 return;
             }
 
-            long requestBody = getHeaderSize(this.headers) + this.postBuffer.capacity();
-            if (options.maxUpload != 0 && requestBody > options.maxUpload) {
-                this.failure("Request body is too large");
+            long requestBody = getHeaderSize( this.headers ) + this.postBuffer.capacity();
+            if( options.maxUpload != 0 && requestBody > options.maxUpload )
+            {
+                this.failure( "Request body is too large" );
                 return;
             }
 
             // Add request size to the tracker before opening the connection
-            this.environment.addTrackingChange(TrackingField.HTTP_REQUESTS, 1);
-            this.environment.addTrackingChange(TrackingField.HTTP_UPLOAD, requestBody);
+            this.environment.addTrackingChange( TrackingField.HTTP_REQUESTS, 1 );
+            this.environment.addTrackingChange( TrackingField.HTTP_UPLOAD, requestBody );
 
-            HttpRequestHandler handler = this.currentRequest = new HttpRequestHandler(this, uri, method, options);
-            this.connectFuture = new Bootstrap().group(NetworkUtils.LOOP_GROUP)
-                                                .channelFactory(NioSocketChannel::new)
-                                                .handler(new ChannelInitializer() {
-                                               @Override
-                                               protected void initChannel(SocketChannel ch) {
+            HttpRequestHandler handler = this.currentRequest = new HttpRequestHandler( this, uri, method, options );
+            this.connectFuture = new Bootstrap().group( NetworkUtils.LOOP_GROUP )
+                .channelFactory( NioSocketChannel::new )
+                .handler( new ChannelInitializer()
+                {
+                    @Override
+                    protected void initChannel( SocketChannel ch )
+                    {
 
-                                                   if (options.timeout > 0) {
-                                                       ch.config()
-                                                         .setConnectTimeoutMillis(options.timeout);
-                                                   }
+                        if( options.timeout > 0 )
+                        {
+                            ch.config()
+                                .setConnectTimeoutMillis( options.timeout );
+                        }
 
-                                                   ChannelPipeline p = ch.pipeline();
-                                                   if (sslContext != null) {
-                                                       p.addLast(sslContext.newHandler(ch.alloc(), uri.getHost(), socketAddress.getPort()));
-                                                   }
+                        ChannelPipeline p = ch.pipeline();
+                        if( sslContext != null )
+                        {
+                            p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) );
+                        }
 
-                                                   if (options.timeout > 0) {
-                                                       p.addLast(new ReadTimeoutHandler(options.timeout, TimeUnit.MILLISECONDS));
-                                                   }
+                        if( options.timeout > 0 )
+                        {
+                            p.addLast( new ReadTimeoutHandler( options.timeout, TimeUnit.MILLISECONDS ) );
+                        }
 
-                                                   p.addLast(new HttpClientCodec(), new HttpContentDecompressor(), handler);
-                                               }
-                                           })
-                                                .remoteAddress(socketAddress)
-                                                .connect()
-                                                .addListener(c -> {
-                                               if (!c.isSuccess()) {
-                                                   this.failure(c.cause());
-                                               }
-                                           });
+                        p.addLast( new HttpClientCodec(), new HttpContentDecompressor(), handler );
+                    }
+                } )
+                .remoteAddress( socketAddress )
+                .connect()
+                .addListener( c -> {
+                    if( !c.isSuccess() )
+                    {
+                        this.failure( c.cause() );
+                    }
+                } );
 
             // Do an additional check for cancellation
             this.checkClosed();
-        } catch (HTTPRequestException e) {
-            this.failure(e.getMessage());
-        } catch (Exception e) {
-            this.failure("Could not connect");
-            if (ComputerCraft.logComputerErrors) {
-                ComputerCraft.log.error("Error in HTTP request", e);
+        }
+        catch( HTTPRequestException e )
+        {
+            this.failure( e.getMessage() );
+        }
+        catch( Exception e )
+        {
+            this.failure( "Could not connect" );
+            if( ComputerCraft.logComputerErrors )
+            {
+                ComputerCraft.log.error( "Error in HTTP request", e );
             }
         }
     }
 
-    public static long getHeaderSize(HttpHeaders headers) {
+    public static long getHeaderSize( HttpHeaders headers )
+    {
         long size = 0;
-        for (Map.Entry header : headers) {
+        for( Map.Entry header : headers )
+        {
             size += header.getKey() == null ? 0 : header.getKey()
-                                                        .length();
+                .length();
             size += header.getValue() == null ? 0 : header.getValue()
-                                                          .length() + 1;
+                .length() + 1;
         }
         return size;
     }
 
-    void failure(String message) {
-        if (this.tryClose()) {
-            this.environment.queueEvent(FAILURE_EVENT, this.address, message);
+    void failure( String message )
+    {
+        if( this.tryClose() )
+        {
+            this.environment.queueEvent( FAILURE_EVENT, this.address, message );
         }
     }
 
-    void failure(Throwable cause) {
+    void failure( Throwable cause )
+    {
         String message;
-        if (cause instanceof HTTPRequestException) {
+        if( cause instanceof HTTPRequestException )
+        {
             message = cause.getMessage();
-        } else if (cause instanceof TooLongFrameException) {
+        }
+        else if( cause instanceof TooLongFrameException )
+        {
             message = "Response is too large";
-        } else if (cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException) {
+        }
+        else if( cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException )
+        {
             message = "Timed out";
-        } else {
+        }
+        else
+        {
             message = "Could not connect";
         }
 
-        this.failure(message);
+        this.failure( message );
     }
 
-    void failure(String message, HttpResponseHandle object) {
-        if (this.tryClose()) {
-            this.environment.queueEvent(FAILURE_EVENT, this.address, message, object);
+    void failure( String message, HttpResponseHandle object )
+    {
+        if( this.tryClose() )
+        {
+            this.environment.queueEvent( FAILURE_EVENT, this.address, message, object );
         }
     }
 
-    void success(HttpResponseHandle object) {
-        if (this.tryClose()) {
-            this.environment.queueEvent(SUCCESS_EVENT, this.address, object);
+    void success( HttpResponseHandle object )
+    {
+        if( this.tryClose() )
+        {
+            this.environment.queueEvent( SUCCESS_EVENT, this.address, object );
         }
     }
 
     @Override
-    protected void dispose() {
+    protected void dispose()
+    {
         super.dispose();
 
-        this.executorFuture = closeFuture(this.executorFuture);
-        this.connectFuture = closeChannel(this.connectFuture);
-        this.currentRequest = closeCloseable(this.currentRequest);
+        this.executorFuture = closeFuture( this.executorFuture );
+        this.connectFuture = closeChannel( this.connectFuture );
+        this.currentRequest = closeCloseable( this.currentRequest );
     }
 
-    public ByteBuf body() {
+    public ByteBuf body()
+    {
         return this.postBuffer;
     }
 
-    public HttpHeaders headers() {
+    public HttpHeaders headers()
+    {
         return this.headers;
     }
 
-    public boolean isBinary() {
+    public boolean isBinary()
+    {
         return this.binary;
     }
 }
diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpResponseHandle.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpResponseHandle.java
index 14cf8cfd7..55436a634 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpResponseHandle.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpResponseHandle.java
@@ -6,11 +6,6 @@
 
 package dan200.computercraft.core.apis.http.request;
 
-import java.util.Collections;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
 import dan200.computercraft.api.lua.IArguments;
 import dan200.computercraft.api.lua.LuaFunction;
 import dan200.computercraft.core.apis.HTTPAPI;
@@ -19,6 +14,10 @@ import dan200.computercraft.core.apis.handles.EncodedReadableHandle;
 import dan200.computercraft.core.apis.handles.HandleGeneric;
 import dan200.computercraft.core.asm.ObjectSource;
 
+import javax.annotation.Nonnull;
+import java.util.Collections;
+import java.util.Map;
+
 /**
  * A http response. This provides the same methods as a {@link EncodedReadableHandle file} (or {@link BinaryReadableHandle binary file} if the request used
  * binary mode), though provides several request specific methods.
@@ -26,13 +25,15 @@ import dan200.computercraft.core.asm.ObjectSource;
  * @cc.module http.Response
  * @see HTTPAPI#request(IArguments)  On how to make a http request.
  */
-public class HttpResponseHandle implements ObjectSource {
+public class HttpResponseHandle implements ObjectSource
+{
     private final Object reader;
     private final int responseCode;
     private final String responseStatus;
     private final Map responseHeaders;
 
-    public HttpResponseHandle(@Nonnull HandleGeneric reader, int responseCode, String responseStatus, @Nonnull Map responseHeaders) {
+    public HttpResponseHandle( @Nonnull HandleGeneric reader, int responseCode, String responseStatus, @Nonnull Map responseHeaders )
+    {
         this.reader = reader;
         this.responseCode = responseCode;
         this.responseStatus = responseStatus;
@@ -47,7 +48,8 @@ public class HttpResponseHandle implements ObjectSource {
      * @cc.treturn string The response message (i.e. "OK")
      */
     @LuaFunction
-    public final Object[] getResponseCode() {
+    public final Object[] getResponseCode()
+    {
         return new Object[] {
             this.responseCode,
             this.responseStatus
@@ -60,7 +62,7 @@ public class HttpResponseHandle implements ObjectSource {
      *
      * @return The response's headers.
      * @cc.usage Make a request to [example.computercraft.cc](https://example.computercraft.cc), and print the returned headers.
-     *     
{@code
+     * 
{@code
      *     local request = http.get("https://example.computercraft.cc")
      *     print(textutils.serialize(request.getResponseHeaders()))
      *     -- => {
@@ -72,12 +74,14 @@ public class HttpResponseHandle implements ObjectSource {
      *     }
*/ @LuaFunction - public final Map getResponseHeaders() { + public final Map getResponseHeaders() + { return this.responseHeaders; } @Override - public Iterable getExtra() { - return Collections.singletonList(this.reader); + public Iterable getExtra() + { + return Collections.singletonList( this.reader ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java index e72647cc0..d559fc193 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java +++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java @@ -6,12 +6,6 @@ package dan200.computercraft.core.apis.http.websocket; -import java.lang.ref.WeakReference; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.concurrent.Future; - import com.google.common.base.Strings; import dan200.computercraft.ComputerCraft; import dan200.computercraft.core.apis.IAPIEnvironment; @@ -37,10 +31,17 @@ import io.netty.handler.codec.http.websocketx.WebSocketVersion; import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler; import io.netty.handler.ssl.SslContext; +import java.lang.ref.WeakReference; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.Future; + /** * Provides functionality to verify and connect to a remote websocket. */ -public class Websocket extends Resource { +public class Websocket extends Resource +{ /** * We declare the maximum size to be 2^30 bytes. While messages can be much longer, we set an arbitrary limit as working with larger messages * (especially within a Lua VM) is absurd. @@ -59,159 +60,199 @@ public class Websocket extends Resource { private ChannelFuture connectFuture; private WeakReference websocketHandle; - public Websocket(ResourceGroup limiter, IAPIEnvironment environment, URI uri, String address, HttpHeaders headers) { - super(limiter); + public Websocket( ResourceGroup limiter, IAPIEnvironment environment, URI uri, String address, HttpHeaders headers ) + { + super( limiter ); this.environment = environment; this.uri = uri; this.address = address; this.headers = headers; } - public static URI checkUri(String address) throws HTTPRequestException { + public static URI checkUri( String address ) throws HTTPRequestException + { URI uri = null; - try { - uri = new URI(address); - } catch (URISyntaxException ignored) { + try + { + uri = new URI( address ); + } + catch( URISyntaxException ignored ) + { } - if (uri == null || uri.getHost() == null) { - try { - uri = new URI("ws://" + address); - } catch (URISyntaxException ignored) { + if( uri == null || uri.getHost() == null ) + { + try + { + uri = new URI( "ws://" + address ); + } + catch( URISyntaxException ignored ) + { } } - if (uri == null || uri.getHost() == null) { - throw new HTTPRequestException("URL malformed"); + if( uri == null || uri.getHost() == null ) + { + throw new HTTPRequestException( "URL malformed" ); } String scheme = uri.getScheme(); - if (scheme == null) { - try { - uri = new URI("ws://" + uri); - } catch (URISyntaxException e) { - throw new HTTPRequestException("URL malformed"); + if( scheme == null ) + { + try + { + uri = new URI( "ws://" + uri ); } - } else if (!scheme.equalsIgnoreCase("wss") && !scheme.equalsIgnoreCase("ws")) { - throw new HTTPRequestException("Invalid scheme '" + scheme + "'"); + catch( URISyntaxException e ) + { + throw new HTTPRequestException( "URL malformed" ); + } + } + else if( !scheme.equalsIgnoreCase( "wss" ) && !scheme.equalsIgnoreCase( "ws" ) ) + { + throw new HTTPRequestException( "Invalid scheme '" + scheme + "'" ); } return uri; } - public void connect() { - if (this.isClosed()) { + public void connect() + { + if( this.isClosed() ) + { return; } - this.executorFuture = NetworkUtils.EXECUTOR.submit(this::doConnect); + this.executorFuture = NetworkUtils.EXECUTOR.submit( this::doConnect ); this.checkClosed(); } - private void doConnect() { + private void doConnect() + { // If we're cancelled, abort. - if (this.isClosed()) { + if( this.isClosed() ) + { return; } - try { + try + { boolean ssl = this.uri.getScheme() - .equalsIgnoreCase("wss"); + .equalsIgnoreCase( "wss" ); - InetSocketAddress socketAddress = NetworkUtils.getAddress(uri, ssl); - Options options = NetworkUtils.getOptions(this.uri.getHost(), socketAddress); + InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl ); + Options options = NetworkUtils.getOptions( this.uri.getHost(), socketAddress ); SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null; // getAddress may have a slight delay, so let's perform another cancellation check. - if (this.isClosed()) { + if( this.isClosed() ) + { return; } - this.connectFuture = new Bootstrap().group(NetworkUtils.LOOP_GROUP) - .channel(NioSocketChannel.class) - .handler(new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel ch) { - ChannelPipeline p = ch.pipeline(); - if (sslContext != null) { - p.addLast(sslContext.newHandler(ch.alloc(), Websocket.this.uri.getHost(), socketAddress.getPort())); - } + this.connectFuture = new Bootstrap().group( NetworkUtils.LOOP_GROUP ) + .channel( NioSocketChannel.class ) + .handler( new ChannelInitializer() + { + @Override + protected void initChannel( SocketChannel ch ) + { + ChannelPipeline p = ch.pipeline(); + if( sslContext != null ) + { + p.addLast( sslContext.newHandler( ch.alloc(), Websocket.this.uri.getHost(), socketAddress.getPort() ) ); + } - WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(Websocket.this.uri, - WebSocketVersion.V13, - null, - true, - Websocket.this.headers, - options.websocketMessage <= 0 ? MAX_MESSAGE_SIZE : options.websocketMessage); + WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker( Websocket.this.uri, + WebSocketVersion.V13, + null, + true, + Websocket.this.headers, + options.websocketMessage <= 0 ? MAX_MESSAGE_SIZE : options.websocketMessage ); - p.addLast(new HttpClientCodec(), - new HttpObjectAggregator(8192), - WebSocketClientCompressionHandler.INSTANCE, - new WebsocketHandler(Websocket.this, handshaker, options)); - } - }) - .remoteAddress(socketAddress) - .connect() - .addListener(c -> { - if (!c.isSuccess()) { - this.failure(c.cause() - .getMessage()); - } - }); + p.addLast( new HttpClientCodec(), + new HttpObjectAggregator( 8192 ), + WebSocketClientCompressionHandler.INSTANCE, + new WebsocketHandler( Websocket.this, handshaker, options ) ); + } + } ) + .remoteAddress( socketAddress ) + .connect() + .addListener( c -> { + if( !c.isSuccess() ) + { + this.failure( c.cause() + .getMessage() ); + } + } ); // Do an additional check for cancellation this.checkClosed(); - } catch (HTTPRequestException e) { - this.failure(e.getMessage()); - } catch (Exception e) { - this.failure("Could not connect"); - if (ComputerCraft.logComputerErrors) { - ComputerCraft.log.error("Error in websocket", e); + } + catch( HTTPRequestException e ) + { + this.failure( e.getMessage() ); + } + catch( Exception e ) + { + this.failure( "Could not connect" ); + if( ComputerCraft.logComputerErrors ) + { + ComputerCraft.log.error( "Error in websocket", e ); } } } - void failure(String message) { - if (this.tryClose()) { - this.environment.queueEvent(FAILURE_EVENT, this.address, message); + void failure( String message ) + { + if( this.tryClose() ) + { + this.environment.queueEvent( FAILURE_EVENT, this.address, message ); } } - void success(Channel channel, Options options) { - if (this.isClosed()) { + void success( Channel channel, Options options ) + { + if( this.isClosed() ) + { return; } - WebsocketHandle handle = new WebsocketHandle(this, options, channel); - this.environment().queueEvent(SUCCESS_EVENT, this.address, handle); - this.websocketHandle = this.createOwnerReference(handle); + WebsocketHandle handle = new WebsocketHandle( this, options, channel ); + this.environment().queueEvent( SUCCESS_EVENT, this.address, handle ); + this.websocketHandle = this.createOwnerReference( handle ); this.checkClosed(); } - public IAPIEnvironment environment() { + public IAPIEnvironment environment() + { return this.environment; } - void close(int status, String reason) { - if (this.tryClose()) { - this.environment.queueEvent(CLOSE_EVENT, this.address, Strings.isNullOrEmpty(reason) ? null : reason, status < 0 ? null : status); + void close( int status, String reason ) + { + if( this.tryClose() ) + { + this.environment.queueEvent( CLOSE_EVENT, this.address, Strings.isNullOrEmpty( reason ) ? null : reason, status < 0 ? null : status ); } } @Override - protected void dispose() { + protected void dispose() + { super.dispose(); - this.executorFuture = closeFuture(this.executorFuture); - this.connectFuture = closeChannel(this.connectFuture); + this.executorFuture = closeFuture( this.executorFuture ); + this.connectFuture = closeChannel( this.connectFuture ); WeakReference websocketHandleRef = this.websocketHandle; WebsocketHandle websocketHandle = websocketHandleRef == null ? null : websocketHandleRef.get(); - IoUtil.closeQuietly(websocketHandle); + IoUtil.closeQuietly( websocketHandle ); this.websocketHandle = null; } - public String address() { + public String address() + { return this.address; } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java index c31c5dd70..4931d2d63 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java +++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java @@ -6,23 +6,8 @@ package dan200.computercraft.core.apis.http.websocket; -import static dan200.computercraft.api.lua.LuaValues.checkFinite; -import static dan200.computercraft.core.apis.IAPIEnvironment.TIMER_EVENT; -import static dan200.computercraft.core.apis.http.websocket.Websocket.CLOSE_EVENT; -import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT; - -import java.io.Closeable; -import java.util.Arrays; -import java.util.Optional; - -import javax.annotation.Nonnull; - import com.google.common.base.Objects; -import dan200.computercraft.api.lua.ILuaCallback; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.LuaValues; -import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.lua.*; import dan200.computercraft.core.apis.http.options.Options; import dan200.computercraft.core.tracking.TrackingField; import dan200.computercraft.shared.util.StringUtil; @@ -31,20 +16,32 @@ import io.netty.channel.Channel; import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import javax.annotation.Nonnull; +import java.io.Closeable; +import java.util.Arrays; +import java.util.Optional; + +import static dan200.computercraft.api.lua.LuaValues.checkFinite; +import static dan200.computercraft.core.apis.IAPIEnvironment.TIMER_EVENT; +import static dan200.computercraft.core.apis.http.websocket.Websocket.CLOSE_EVENT; +import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT; + /** * A websocket, which can be used to send an receive messages with a web server. * * @cc.module http.Websocket * @see dan200.computercraft.core.apis.HTTPAPI#websocket On how to open a websocket. */ -public class WebsocketHandle implements Closeable { +public class WebsocketHandle implements Closeable +{ private final Websocket websocket; private final Options options; private boolean closed = false; private Channel channel; - public WebsocketHandle(Websocket websocket, Options options, Channel channel) { + public WebsocketHandle( Websocket websocket, Options options, Channel channel ) + { this.websocket = websocket; this.options = options; this.channel = channel; @@ -61,17 +58,20 @@ public class WebsocketHandle implements Closeable { * @cc.treturn [2] nil If the websocket was closed while waiting, or if we timed out. */ @LuaFunction - public final MethodResult receive(Optional timeout) throws LuaException { + public final MethodResult receive( Optional timeout ) throws LuaException + { this.checkOpen(); int timeoutId = timeout.isPresent() ? this.websocket.environment() - .startTimer(Math.round(checkFinite(0, timeout.get()) / 0.05)) : -1; + .startTimer( Math.round( checkFinite( 0, timeout.get() ) / 0.05 ) ) : -1; - return new ReceiveCallback(timeoutId).pull; + return new ReceiveCallback( timeoutId ).pull; } - private void checkOpen() throws LuaException { - if (this.closed) { - throw new LuaException("attempt to use a closed file"); + private void checkOpen() throws LuaException + { + if( this.closed ) + { + throw new LuaException( "attempt to use a closed file" ); } } @@ -79,67 +79,81 @@ public class WebsocketHandle implements Closeable { * Send a websocket message to the connected server. * * @param message The message to send. - * @param binary Whether this message should be treated as a + * @param binary Whether this message should be treated as a * @throws LuaException If the message is too large. * @throws LuaException If the websocket has been closed. */ @LuaFunction - public final void send(Object message, Optional binary) throws LuaException { + public final void send( Object message, Optional binary ) throws LuaException + { this.checkOpen(); - String text = StringUtil.toString(message); - if (this.options.websocketMessage != 0 && text.length() > this.options.websocketMessage) { - throw new LuaException("Message is too large"); + String text = StringUtil.toString( message ); + if( this.options.websocketMessage != 0 && text.length() > this.options.websocketMessage ) + { + throw new LuaException( "Message is too large" ); } this.websocket.environment() - .addTrackingChange(TrackingField.WEBSOCKET_OUTGOING, text.length()); + .addTrackingChange( TrackingField.WEBSOCKET_OUTGOING, text.length() ); Channel channel = this.channel; - if (channel != null) { - channel.writeAndFlush(binary.orElse(false) ? new BinaryWebSocketFrame(Unpooled.wrappedBuffer(LuaValues.encode(text))) : new TextWebSocketFrame( - text)); + if( channel != null ) + { + channel.writeAndFlush( binary.orElse( false ) ? new BinaryWebSocketFrame( Unpooled.wrappedBuffer( LuaValues.encode( text ) ) ) : new TextWebSocketFrame( + text ) ); } } /** * Close this websocket. This will terminate the connection, meaning messages can no longer be sent or received along it. */ - @LuaFunction ("close") - public final void doClose() { + @LuaFunction( "close" ) + public final void doClose() + { this.close(); this.websocket.close(); } @Override - public void close() { + public void close() + { this.closed = true; Channel channel = this.channel; - if (channel != null) { + if( channel != null ) + { channel.close(); this.channel = null; } } - private final class ReceiveCallback implements ILuaCallback { - final MethodResult pull = MethodResult.pullEvent(null, this); + private final class ReceiveCallback implements ILuaCallback + { + final MethodResult pull = MethodResult.pullEvent( null, this ); private final int timeoutId; - ReceiveCallback(int timeoutId) { + ReceiveCallback( int timeoutId ) + { this.timeoutId = timeoutId; } @Nonnull @Override - public MethodResult resume(Object[] event) { - if (event.length >= 3 && Objects.equal(event[0], MESSAGE_EVENT) && Objects.equal(event[1], WebsocketHandle.this.websocket.address())) { - return MethodResult.of(Arrays.copyOfRange(event, 2, event.length)); - } else if (event.length >= 2 && Objects.equal(event[0], CLOSE_EVENT) && Objects.equal(event[1], WebsocketHandle.this.websocket.address()) && WebsocketHandle.this.closed) { + public MethodResult resume( Object[] event ) + { + if( event.length >= 3 && Objects.equal( event[0], MESSAGE_EVENT ) && Objects.equal( event[1], WebsocketHandle.this.websocket.address() ) ) + { + return MethodResult.of( Arrays.copyOfRange( event, 2, event.length ) ); + } + else if( event.length >= 2 && Objects.equal( event[0], CLOSE_EVENT ) && Objects.equal( event[1], WebsocketHandle.this.websocket.address() ) && WebsocketHandle.this.closed ) + { // If the socket is closed abort. return MethodResult.of(); - } else if (event.length >= 2 && this.timeoutId != -1 && Objects.equal(event[0], - TIMER_EVENT) && event[1] instanceof Number && ((Number) event[1]).intValue() == this.timeoutId) { + } + else if( event.length >= 2 && this.timeoutId != -1 && Objects.equal( event[0], + TIMER_EVENT ) && event[1] instanceof Number && ((Number) event[1]).intValue() == this.timeoutId ) + { // If we received a matching timer event then abort. return MethodResult.of(); } diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java index 600db3b31..7aa2fdd30 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java +++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java @@ -6,8 +6,6 @@ package dan200.computercraft.core.apis.http.websocket; -import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT; - import dan200.computercraft.core.apis.http.HTTPRequestException; import dan200.computercraft.core.apis.http.NetworkUtils; import dan200.computercraft.core.apis.http.options.Options; @@ -17,103 +15,124 @@ import io.netty.channel.ConnectTimeoutException; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.TooLongFrameException; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException; +import io.netty.handler.codec.http.websocketx.*; import io.netty.handler.timeout.ReadTimeoutException; import io.netty.util.CharsetUtil; -public class WebsocketHandler extends SimpleChannelInboundHandler { +import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT; + +public class WebsocketHandler extends SimpleChannelInboundHandler +{ private final Websocket websocket; private final WebSocketClientHandshaker handshaker; private final Options options; - public WebsocketHandler(Websocket websocket, WebSocketClientHandshaker handshaker, Options options) { + public WebsocketHandler( Websocket websocket, WebSocketClientHandshaker handshaker, Options options ) + { this.handshaker = handshaker; this.websocket = websocket; this.options = options; } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - this.handshaker.handshake(ctx.channel()); - super.channelActive(ctx); + public void channelActive( ChannelHandlerContext ctx ) throws Exception + { + this.handshaker.handshake( ctx.channel() ); + super.channelActive( ctx ); } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - this.websocket.close(-1, "Websocket is inactive"); - super.channelInactive(ctx); + public void channelInactive( ChannelHandlerContext ctx ) throws Exception + { + this.websocket.close( -1, "Websocket is inactive" ); + super.channelInactive( ctx ); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) + { ctx.close(); String message; - if (cause instanceof WebSocketHandshakeException || cause instanceof HTTPRequestException) { + if( cause instanceof WebSocketHandshakeException || cause instanceof HTTPRequestException ) + { message = cause.getMessage(); - } else if (cause instanceof TooLongFrameException) { + } + else if( cause instanceof TooLongFrameException ) + { message = "Message is too large"; - } else if (cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException) { + } + else if( cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException ) + { message = "Timed out"; - } else { + } + else + { message = "Could not connect"; } - if (this.handshaker.isHandshakeComplete()) { - this.websocket.close(-1, message); - } else { - this.websocket.failure(message); + if( this.handshaker.isHandshakeComplete() ) + { + this.websocket.close( -1, message ); + } + else + { + this.websocket.failure( message ); } } @Override - public void channelRead0(ChannelHandlerContext ctx, Object msg) { - if (this.websocket.isClosed()) { + public void channelRead0( ChannelHandlerContext ctx, Object msg ) + { + if( this.websocket.isClosed() ) + { return; } - if (!this.handshaker.isHandshakeComplete()) { - this.handshaker.finishHandshake(ctx.channel(), (FullHttpResponse) msg); - this.websocket.success(ctx.channel(), this.options); + if( !this.handshaker.isHandshakeComplete() ) + { + this.handshaker.finishHandshake( ctx.channel(), (FullHttpResponse) msg ); + this.websocket.success( ctx.channel(), this.options ); return; } - if (msg instanceof FullHttpResponse) { + if( msg instanceof FullHttpResponse ) + { FullHttpResponse response = (FullHttpResponse) msg; - throw new IllegalStateException("Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content() - .toString(CharsetUtil.UTF_8) + ')'); + throw new IllegalStateException( "Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content() + .toString( CharsetUtil.UTF_8 ) + ')' ); } WebSocketFrame frame = (WebSocketFrame) msg; - if (frame instanceof TextWebSocketFrame) { + if( frame instanceof TextWebSocketFrame ) + { String data = ((TextWebSocketFrame) frame).text(); this.websocket.environment() - .addTrackingChange(TrackingField.WEBSOCKET_INCOMING, data.length()); + .addTrackingChange( TrackingField.WEBSOCKET_INCOMING, data.length() ); this.websocket.environment() - .queueEvent(MESSAGE_EVENT, this.websocket.address(), data, false); - } else if (frame instanceof BinaryWebSocketFrame) { - byte[] converted = NetworkUtils.toBytes(frame.content()); + .queueEvent( MESSAGE_EVENT, this.websocket.address(), data, false ); + } + else if( frame instanceof BinaryWebSocketFrame ) + { + byte[] converted = NetworkUtils.toBytes( frame.content() ); this.websocket.environment() - .addTrackingChange(TrackingField.WEBSOCKET_INCOMING, converted.length); + .addTrackingChange( TrackingField.WEBSOCKET_INCOMING, converted.length ); this.websocket.environment() - .queueEvent(MESSAGE_EVENT, this.websocket.address(), converted, true); - } else if (frame instanceof CloseWebSocketFrame) { + .queueEvent( MESSAGE_EVENT, this.websocket.address(), converted, true ); + } + else if( frame instanceof CloseWebSocketFrame ) + { CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame; - this.websocket.close(closeFrame.statusCode(), closeFrame.reasonText()); - } else if (frame instanceof PingWebSocketFrame) { + this.websocket.close( closeFrame.statusCode(), closeFrame.reasonText() ); + } + else if( frame instanceof PingWebSocketFrame ) + { frame.content() - .retain(); + .retain(); ctx.channel() - .writeAndFlush(new PongWebSocketFrame(frame.content())); + .writeAndFlush( new PongWebSocketFrame( frame.content() ) ); } } } diff --git a/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java b/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java index 4d9ea0e9d..404c02715 100644 --- a/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java +++ b/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java @@ -7,14 +7,17 @@ package dan200.computercraft.core.asm; import java.security.ProtectionDomain; -final class DeclaringClassLoader extends ClassLoader { +final class DeclaringClassLoader extends ClassLoader +{ static final DeclaringClassLoader INSTANCE = new DeclaringClassLoader(); - private DeclaringClassLoader() { - super(DeclaringClassLoader.class.getClassLoader()); + private DeclaringClassLoader() + { + super( DeclaringClassLoader.class.getClassLoader() ); } - Class define(String name, byte[] bytes, ProtectionDomain protectionDomain) throws ClassFormatError { - return this.defineClass(name, bytes, 0, bytes.length, protectionDomain); + Class define( String name, byte[] bytes, ProtectionDomain protectionDomain ) throws ClassFormatError + { + return this.defineClass( name, bytes, 0, bytes.length, protectionDomain ); } } diff --git a/src/main/java/dan200/computercraft/core/asm/Generator.java b/src/main/java/dan200/computercraft/core/asm/Generator.java index a3c028076..4da5a1b70 100644 --- a/src/main/java/dan200/computercraft/core/asm/Generator.java +++ b/src/main/java/dan200/computercraft/core/asm/Generator.java @@ -5,18 +5,22 @@ */ package dan200.computercraft.core.asm; -import static org.objectweb.asm.Opcodes.ACC_FINAL; -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import static org.objectweb.asm.Opcodes.ALOAD; -import static org.objectweb.asm.Opcodes.ARETURN; -import static org.objectweb.asm.Opcodes.CHECKCAST; -import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; -import static org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static org.objectweb.asm.Opcodes.INVOKESTATIC; -import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; -import static org.objectweb.asm.Opcodes.RETURN; -import static org.objectweb.asm.Opcodes.V1_8; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.primitives.Primitives; +import com.google.common.reflect.TypeToken; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -27,31 +31,20 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import static org.objectweb.asm.Opcodes.*; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.primitives.Primitives; -import com.google.common.reflect.TypeToken; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.*; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Type; - -public final class Generator { +public final class Generator +{ private static final AtomicInteger METHOD_ID = new AtomicInteger(); private static final String METHOD_NAME = "apply"; - private static final String[] EXCEPTIONS = new String[] {Type.getInternalName(LuaException.class)}; + private static final String[] EXCEPTIONS = new String[] { Type.getInternalName( LuaException.class ) }; - private static final String INTERNAL_METHOD_RESULT = Type.getInternalName(MethodResult.class); - private static final String DESC_METHOD_RESULT = Type.getDescriptor(MethodResult.class); + private static final String INTERNAL_METHOD_RESULT = Type.getInternalName( MethodResult.class ); + private static final String DESC_METHOD_RESULT = Type.getDescriptor( MethodResult.class ); - private static final String INTERNAL_ARGUMENTS = Type.getInternalName(IArguments.class); - private static final String DESC_ARGUMENTS = Type.getDescriptor(IArguments.class); + private static final String INTERNAL_ARGUMENTS = Type.getInternalName( IArguments.class ); + private static final String DESC_ARGUMENTS = Type.getDescriptor( IArguments.class ); private final Class base; private final List> context; @@ -61,229 +54,273 @@ public final class Generator { private final Function wrap; private final LoadingCache> methodCache = CacheBuilder.newBuilder() - .build(CacheLoader.from(catching(this::build, Optional.empty()))); + .build( CacheLoader.from( catching( this::build, Optional.empty() ) ) ); private final LoadingCache, List>> classCache = CacheBuilder.newBuilder() - .build(CacheLoader.from(catching(this::build, Collections.emptyList()))); + .build( CacheLoader.from( catching( this::build, Collections.emptyList() ) ) ); - Generator(Class base, List> context, Function wrap) { + Generator( Class base, List> context, Function wrap ) + { this.base = base; this.context = context; - this.interfaces = new String[] {Type.getInternalName(base)}; + this.interfaces = new String[] { Type.getInternalName( base ) }; this.wrap = wrap; - StringBuilder methodDesc = new StringBuilder().append("(Ljava/lang/Object;"); - for (Class klass : context) { - methodDesc.append(Type.getDescriptor(klass)); + StringBuilder methodDesc = new StringBuilder().append( "(Ljava/lang/Object;" ); + for( Class klass : context ) + { + methodDesc.append( Type.getDescriptor( klass ) ); } - methodDesc.append(DESC_ARGUMENTS) - .append(")") - .append(DESC_METHOD_RESULT); + methodDesc.append( DESC_ARGUMENTS ) + .append( ")" ) + .append( DESC_METHOD_RESULT ); this.methodDesc = methodDesc.toString(); } @Nonnull - public List> getMethods(@Nonnull Class klass) { - try { - return this.classCache.get(klass); - } catch (ExecutionException e) { - ComputerCraft.log.error("Error getting methods for {}.", klass.getName(), e.getCause()); + public List> getMethods( @Nonnull Class klass ) + { + try + { + return this.classCache.get( klass ); + } + catch( ExecutionException e ) + { + ComputerCraft.log.error( "Error getting methods for {}.", klass.getName(), e.getCause() ); return Collections.emptyList(); } } @Nonnull - private List> build(Class klass) { + private List> build( Class klass ) + { ArrayList> methods = null; - for (Method method : klass.getMethods()) { - LuaFunction annotation = method.getAnnotation(LuaFunction.class); - if (annotation == null) { + for( Method method : klass.getMethods() ) + { + LuaFunction annotation = method.getAnnotation( LuaFunction.class ); + if( annotation == null ) + { continue; } - if (Modifier.isStatic(method.getModifiers())) { - ComputerCraft.log.warn("LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName()); + if( Modifier.isStatic( method.getModifiers() ) ) + { + ComputerCraft.log.warn( "LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName() ); continue; } - T instance = this.methodCache.getUnchecked(method) - .orElse(null); - if (instance == null) { + T instance = this.methodCache.getUnchecked( method ) + .orElse( null ); + if( instance == null ) + { continue; } - if (methods == null) { + if( methods == null ) + { methods = new ArrayList<>(); } - this.addMethod(methods, method, annotation, instance); + this.addMethod( methods, method, annotation, instance ); } for( GenericMethod method : GenericMethod.all() ) { if( !method.target.isAssignableFrom( klass ) ) continue; - T instance = this.methodCache.getUnchecked(method.method) - .orElse(null); - if (instance == null) { + T instance = this.methodCache.getUnchecked( method.method ) + .orElse( null ); + if( instance == null ) + { continue; } - if (methods == null) { + if( methods == null ) + { methods = new ArrayList<>(); } - this.addMethod(methods, method.method, method.annotation, instance); + this.addMethod( methods, method.method, method.annotation, instance ); } - if (methods == null) { + if( methods == null ) + { return Collections.emptyList(); } methods.trimToSize(); - return Collections.unmodifiableList(methods); + return Collections.unmodifiableList( methods ); } - private void addMethod(List> methods, Method method, LuaFunction annotation, T instance) { - if (annotation.mainThread()) { - instance = this.wrap.apply(instance); + private void addMethod( List> methods, Method method, LuaFunction annotation, T instance ) + { + if( annotation.mainThread() ) + { + instance = this.wrap.apply( instance ); } String[] names = annotation.value(); boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread(); - if (names.length == 0) { - methods.add(new NamedMethod<>(method.getName(), instance, isSimple)); - } else { - for (String name : names) { - methods.add(new NamedMethod<>(name, instance, isSimple)); + if( names.length == 0 ) + { + methods.add( new NamedMethod<>( method.getName(), instance, isSimple ) ); + } + else + { + for( String name : names ) + { + methods.add( new NamedMethod<>( name, instance, isSimple ) ); } } } @Nonnull - private Optional build(Method method) { + private Optional build( Method method ) + { String name = method.getDeclaringClass() - .getName() + "." + method.getName(); + .getName() + "." + method.getName(); int modifiers = method.getModifiers(); // Instance methods must be final - this prevents them being overridden and potentially exposed twice. - if (!Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) { - ComputerCraft.log.warn("Lua Method {} should be final.", name); + if( !Modifier.isStatic( modifiers ) && !Modifier.isFinal( modifiers ) ) + { + ComputerCraft.log.warn( "Lua Method {} should be final.", name ); } - if (!Modifier.isPublic(modifiers)) { - ComputerCraft.log.error("Lua Method {} should be a public method.", name); + if( !Modifier.isPublic( modifiers ) ) + { + ComputerCraft.log.error( "Lua Method {} should be a public method.", name ); return Optional.empty(); } - if (!Modifier.isPublic(method.getDeclaringClass() - .getModifiers())) { - ComputerCraft.log.error("Lua Method {} should be on a public class.", name); + if( !Modifier.isPublic( method.getDeclaringClass() + .getModifiers() ) ) + { + ComputerCraft.log.error( "Lua Method {} should be on a public class.", name ); return Optional.empty(); } - ComputerCraft.log.debug("Generating method wrapper for {}.", name); + ComputerCraft.log.debug( "Generating method wrapper for {}.", name ); Class[] exceptions = method.getExceptionTypes(); - for (Class exception : exceptions) { - if (exception != LuaException.class) { - ComputerCraft.log.error("Lua Method {} cannot throw {}.", name, exception.getName()); + for( Class exception : exceptions ) + { + if( exception != LuaException.class ) + { + ComputerCraft.log.error( "Lua Method {} cannot throw {}.", name, exception.getName() ); return Optional.empty(); } } // We have some rather ugly handling of static methods in both here and the main generate function. Static methods // only come from generic sources, so this should be safe. - Class target = Modifier.isStatic(modifiers) ? method.getParameterTypes()[0] : method.getDeclaringClass(); + Class target = Modifier.isStatic( modifiers ) ? method.getParameterTypes()[0] : method.getDeclaringClass(); - try { + try + { String className = method.getDeclaringClass() - .getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement(); - byte[] bytes = this.generate(className, target, method); - if (bytes == null) { + .getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement(); + byte[] bytes = this.generate( className, target, method ); + if( bytes == null ) + { return Optional.empty(); } - Class klass = DeclaringClassLoader.INSTANCE.define(className, - bytes, - method.getDeclaringClass() - .getProtectionDomain()); - return Optional.of(klass.asSubclass(this.base) - .getDeclaredConstructor() - .newInstance()); - } catch (ReflectiveOperationException | ClassFormatError | RuntimeException e) { - ComputerCraft.log.error("Error generating wrapper for {}.", name, e); + Class klass = DeclaringClassLoader.INSTANCE.define( className, + bytes, + method.getDeclaringClass() + .getProtectionDomain() ); + return Optional.of( klass.asSubclass( this.base ) + .getDeclaredConstructor() + .newInstance() ); + } + catch( ReflectiveOperationException | ClassFormatError | RuntimeException e ) + { + ComputerCraft.log.error( "Error generating wrapper for {}.", name, e ); return Optional.empty(); } } @Nullable - private byte[] generate(String className, Class target, Method method) { - String internalName = className.replace(".", "/"); + private byte[] generate( String className, Class target, Method method ) + { + String internalName = className.replace( ".", "/" ); // Construct a public final class which extends Object and implements MethodInstance.Delegate - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - cw.visit(V1_8, ACC_PUBLIC | ACC_FINAL, internalName, null, "java/lang/Object", this.interfaces); - cw.visitSource("CC generated method", null); + ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS ); + cw.visit( V1_8, ACC_PUBLIC | ACC_FINAL, internalName, null, "java/lang/Object", this.interfaces ); + cw.visitSource( "CC generated method", null ); { // Constructor just invokes super. - MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + MethodVisitor mw = cw.visitMethod( ACC_PUBLIC, "", "()V", null, null ); mw.visitCode(); - mw.visitVarInsn(ALOAD, 0); - mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mw.visitInsn(RETURN); - mw.visitMaxs(0, 0); + mw.visitVarInsn( ALOAD, 0 ); + mw.visitMethodInsn( INVOKESPECIAL, "java/lang/Object", "", "()V", false ); + mw.visitInsn( RETURN ); + mw.visitMaxs( 0, 0 ); mw.visitEnd(); } { - MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, METHOD_NAME, this.methodDesc, null, EXCEPTIONS); + MethodVisitor mw = cw.visitMethod( ACC_PUBLIC, METHOD_NAME, this.methodDesc, null, EXCEPTIONS ); mw.visitCode(); // If we're an instance method, load the this parameter. - if (!Modifier.isStatic(method.getModifiers())) { - mw.visitVarInsn(ALOAD, 1); - mw.visitTypeInsn(CHECKCAST, Type.getInternalName(target)); + if( !Modifier.isStatic( method.getModifiers() ) ) + { + mw.visitVarInsn( ALOAD, 1 ); + mw.visitTypeInsn( CHECKCAST, Type.getInternalName( target ) ); } int argIndex = 0; - for (java.lang.reflect.Type genericArg : method.getGenericParameterTypes()) { - Boolean loadedArg = this.loadArg(mw, target, method, genericArg, argIndex); - if (loadedArg == null) { + for( java.lang.reflect.Type genericArg : method.getGenericParameterTypes() ) + { + Boolean loadedArg = this.loadArg( mw, target, method, genericArg, argIndex ); + if( loadedArg == null ) + { return null; } - if (loadedArg) { + if( loadedArg ) + { argIndex++; } } - mw.visitMethodInsn(Modifier.isStatic(method.getModifiers()) ? INVOKESTATIC : INVOKEVIRTUAL, - Type.getInternalName(method.getDeclaringClass()), - method.getName(), - Type.getMethodDescriptor(method), - false); + mw.visitMethodInsn( Modifier.isStatic( method.getModifiers() ) ? INVOKESTATIC : INVOKEVIRTUAL, + Type.getInternalName( method.getDeclaringClass() ), + method.getName(), + Type.getMethodDescriptor( method ), + false ); // We allow a reasonable amount of flexibility on the return value's type. Alongside the obvious MethodResult, // we convert basic types into an immediate result. Class ret = method.getReturnType(); - if (ret != MethodResult.class) { - if (ret == void.class) { - mw.visitMethodInsn(INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "()" + DESC_METHOD_RESULT, false); - } else if (ret.isPrimitive()) { - Class boxed = Primitives.wrap(ret); - mw.visitMethodInsn(INVOKESTATIC, - Type.getInternalName(boxed), - "valueOf", - "(" + Type.getDescriptor(ret) + ")" + Type.getDescriptor(boxed), - false); - mw.visitMethodInsn(INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "(Ljava/lang/Object;)" + DESC_METHOD_RESULT, false); - } else if (ret == Object[].class) { - mw.visitMethodInsn(INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "([Ljava/lang/Object;)" + DESC_METHOD_RESULT, false); - } else { - mw.visitMethodInsn(INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "(Ljava/lang/Object;)" + DESC_METHOD_RESULT, false); + if( ret != MethodResult.class ) + { + if( ret == void.class ) + { + mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "()" + DESC_METHOD_RESULT, false ); + } + else if( ret.isPrimitive() ) + { + Class boxed = Primitives.wrap( ret ); + mw.visitMethodInsn( INVOKESTATIC, + Type.getInternalName( boxed ), + "valueOf", + "(" + Type.getDescriptor( ret ) + ")" + Type.getDescriptor( boxed ), + false ); + mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "(Ljava/lang/Object;)" + DESC_METHOD_RESULT, false ); + } + else if( ret == Object[].class ) + { + mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "([Ljava/lang/Object;)" + DESC_METHOD_RESULT, false ); + } + else + { + mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "(Ljava/lang/Object;)" + DESC_METHOD_RESULT, false ); } } - mw.visitInsn(ARETURN); + mw.visitInsn( ARETURN ); - mw.visitMaxs(0, 0); + mw.visitMaxs( 0, 0 ); mw.visitEnd(); } @@ -292,82 +329,94 @@ public final class Generator { return cw.toByteArray(); } - private Boolean loadArg(MethodVisitor mw, Class target, Method method, java.lang.reflect.Type genericArg, int argIndex) { - if (genericArg == target) { - mw.visitVarInsn(ALOAD, 1); - mw.visitTypeInsn(CHECKCAST, Type.getInternalName(target)); + private Boolean loadArg( MethodVisitor mw, Class target, Method method, java.lang.reflect.Type genericArg, int argIndex ) + { + if( genericArg == target ) + { + mw.visitVarInsn( ALOAD, 1 ); + mw.visitTypeInsn( CHECKCAST, Type.getInternalName( target ) ); return false; } - Class arg = Reflect.getRawType(method, genericArg, true); - if (arg == null) { + Class arg = Reflect.getRawType( method, genericArg, true ); + if( arg == null ) + { return null; } - if (arg == IArguments.class) { - mw.visitVarInsn(ALOAD, 2 + this.context.size()); + if( arg == IArguments.class ) + { + mw.visitVarInsn( ALOAD, 2 + this.context.size() ); return false; } - int idx = this.context.indexOf(arg); - if (idx >= 0) { - mw.visitVarInsn(ALOAD, 2 + idx); + int idx = this.context.indexOf( arg ); + if( idx >= 0 ) + { + mw.visitVarInsn( ALOAD, 2 + idx ); return false; } - if (arg == Optional.class) { - Class klass = Reflect.getRawType(method, - TypeToken.of(genericArg) - .resolveType(Reflect.OPTIONAL_IN) - .getType(), - false); - if (klass == null) { + if( arg == Optional.class ) + { + Class klass = Reflect.getRawType( method, + TypeToken.of( genericArg ) + .resolveType( Reflect.OPTIONAL_IN ) + .getType(), + false ); + if( klass == null ) + { return null; } - if (Enum.class.isAssignableFrom(klass) && klass != Enum.class) { - mw.visitVarInsn(ALOAD, 2 + this.context.size()); - Reflect.loadInt(mw, argIndex); - mw.visitLdcInsn(Type.getType(klass)); - mw.visitMethodInsn(INVOKEINTERFACE, INTERNAL_ARGUMENTS, "optEnum", "(ILjava/lang/Class;)Ljava/util/Optional;", true); + if( Enum.class.isAssignableFrom( klass ) && klass != Enum.class ) + { + mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + Reflect.loadInt( mw, argIndex ); + mw.visitLdcInsn( Type.getType( klass ) ); + mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "optEnum", "(ILjava/lang/Class;)Ljava/util/Optional;", true ); return true; } - String name = Reflect.getLuaName(Primitives.unwrap(klass)); - if (name != null) { - mw.visitVarInsn(ALOAD, 2 + this.context.size()); - Reflect.loadInt(mw, argIndex); - mw.visitMethodInsn(INVOKEINTERFACE, INTERNAL_ARGUMENTS, "opt" + name, "(I)Ljava/util/Optional;", true); + String name = Reflect.getLuaName( Primitives.unwrap( klass ) ); + if( name != null ) + { + mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + Reflect.loadInt( mw, argIndex ); + mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "opt" + name, "(I)Ljava/util/Optional;", true ); return true; } } - if (Enum.class.isAssignableFrom(arg) && arg != Enum.class) { - mw.visitVarInsn(ALOAD, 2 + this.context.size()); - Reflect.loadInt(mw, argIndex); - mw.visitLdcInsn(Type.getType(arg)); - mw.visitMethodInsn(INVOKEINTERFACE, INTERNAL_ARGUMENTS, "getEnum", "(ILjava/lang/Class;)Ljava/lang/Enum;", true); - mw.visitTypeInsn(CHECKCAST, Type.getInternalName(arg)); + if( Enum.class.isAssignableFrom( arg ) && arg != Enum.class ) + { + mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + Reflect.loadInt( mw, argIndex ); + mw.visitLdcInsn( Type.getType( arg ) ); + mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "getEnum", "(ILjava/lang/Class;)Ljava/lang/Enum;", true ); + mw.visitTypeInsn( CHECKCAST, Type.getInternalName( arg ) ); return true; } - String name = arg == Object.class ? "" : Reflect.getLuaName(arg); - if (name != null) { - if (Reflect.getRawType(method, genericArg, false) == null) { + String name = arg == Object.class ? "" : Reflect.getLuaName( arg ); + if( name != null ) + { + if( Reflect.getRawType( method, genericArg, false ) == null ) + { return null; } - mw.visitVarInsn(ALOAD, 2 + this.context.size()); - Reflect.loadInt(mw, argIndex); - mw.visitMethodInsn(INVOKEINTERFACE, INTERNAL_ARGUMENTS, "get" + name, "(I)" + Type.getDescriptor(arg), true); + mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + Reflect.loadInt( mw, argIndex ); + mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "get" + name, "(I)" + Type.getDescriptor( arg ), true ); return true; } - ComputerCraft.log.error("Unknown parameter type {} for method {}.{}.", - arg.getName(), - method.getDeclaringClass() - .getName(), - method.getName()); + ComputerCraft.log.error( "Unknown parameter type {} for method {}.{}.", + arg.getName(), + method.getDeclaringClass() + .getName(), + method.getName() ); return null; } diff --git a/src/main/java/dan200/computercraft/core/asm/IntCache.java b/src/main/java/dan200/computercraft/core/asm/IntCache.java index de56d79ae..cb1056dee 100644 --- a/src/main/java/dan200/computercraft/core/asm/IntCache.java +++ b/src/main/java/dan200/computercraft/core/asm/IntCache.java @@ -8,34 +8,43 @@ package dan200.computercraft.core.asm; import java.util.Arrays; import java.util.function.IntFunction; -public final class IntCache { +public final class IntCache +{ private final IntFunction factory; private volatile Object[] cache = new Object[16]; - IntCache(IntFunction factory) { + IntCache( IntFunction factory ) + { this.factory = factory; } - @SuppressWarnings ("unchecked") - public T get(int index) { - if (index < 0) { - throw new IllegalArgumentException("index < 0"); + @SuppressWarnings( "unchecked" ) + public T get( int index ) + { + if( index < 0 ) + { + throw new IllegalArgumentException( "index < 0" ); } - if (index < this.cache.length) { + if( index < this.cache.length ) + { T current = (T) this.cache[index]; - if (current != null) { + if( current != null ) + { return current; } } - synchronized (this) { - if (index >= this.cache.length) { - this.cache = Arrays.copyOf(this.cache, Math.max(this.cache.length * 2, index + 1)); + synchronized( this ) + { + if( index >= this.cache.length ) + { + this.cache = Arrays.copyOf( this.cache, Math.max( this.cache.length * 2, index + 1 ) ); } T current = (T) this.cache[index]; - if (current == null) { - this.cache[index] = current = this.factory.apply(index); + if( current == null ) + { + this.cache[index] = current = this.factory.apply( index ); } return current; } diff --git a/src/main/java/dan200/computercraft/core/asm/LuaMethod.java b/src/main/java/dan200/computercraft/core/asm/LuaMethod.java index b0bb19b54..87c454878 100644 --- a/src/main/java/dan200/computercraft/core/asm/LuaMethod.java +++ b/src/main/java/dan200/computercraft/core/asm/LuaMethod.java @@ -5,28 +5,24 @@ */ package dan200.computercraft.core.asm; -import java.util.Collections; +import dan200.computercraft.api.lua.*; import javax.annotation.Nonnull; +import java.util.Collections; -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.MethodResult; +public interface LuaMethod +{ + Generator GENERATOR = new Generator<>( LuaMethod.class, + Collections.singletonList( ILuaContext.class ), + m -> ( target, context, args ) -> TaskCallback.make( context, + () -> TaskCallback.checkUnwrap( m.apply( target, + context, + args ) ) ) ); -public interface LuaMethod { - Generator GENERATOR = new Generator<>(LuaMethod.class, - Collections.singletonList(ILuaContext.class), - m -> (target, context, args) -> TaskCallback.make(context, - () -> TaskCallback.checkUnwrap(m.apply(target, - context, - args)))); - - IntCache DYNAMIC = new IntCache<>(method -> (instance, context, args) -> ((IDynamicLuaObject) instance).callMethod(context, method, args)); + IntCache DYNAMIC = new IntCache<>( method -> ( instance, context, args ) -> ((IDynamicLuaObject) instance).callMethod( context, method, args ) ); String[] EMPTY_METHODS = new String[0]; @Nonnull - MethodResult apply(@Nonnull Object target, @Nonnull ILuaContext context, @Nonnull IArguments args) throws LuaException; + MethodResult apply( @Nonnull Object target, @Nonnull ILuaContext context, @Nonnull IArguments args ) throws LuaException; } diff --git a/src/main/java/dan200/computercraft/core/asm/NamedMethod.java b/src/main/java/dan200/computercraft/core/asm/NamedMethod.java index 7edd17f05..ffb6e0b8b 100644 --- a/src/main/java/dan200/computercraft/core/asm/NamedMethod.java +++ b/src/main/java/dan200/computercraft/core/asm/NamedMethod.java @@ -7,28 +7,33 @@ package dan200.computercraft.core.asm; import javax.annotation.Nonnull; -public final class NamedMethod { +public final class NamedMethod +{ private final String name; private final T method; private final boolean nonYielding; - NamedMethod(String name, T method, boolean nonYielding) { + NamedMethod( String name, T method, boolean nonYielding ) + { this.name = name; this.method = method; this.nonYielding = nonYielding; } @Nonnull - public String getName() { + public String getName() + { return this.name; } @Nonnull - public T getMethod() { + public T getMethod() + { return this.method; } - public boolean nonYielding() { + public boolean nonYielding() + { return this.nonYielding; } } diff --git a/src/main/java/dan200/computercraft/core/asm/ObjectSource.java b/src/main/java/dan200/computercraft/core/asm/ObjectSource.java index b696867b9..9ea11f60d 100644 --- a/src/main/java/dan200/computercraft/core/asm/ObjectSource.java +++ b/src/main/java/dan200/computercraft/core/asm/ObjectSource.java @@ -13,16 +13,22 @@ import java.util.function.BiConsumer; * This can be used to merge multiple objects together into one. Ideally this'd be part of the API, but I'm not entirely happy with the interface - * something I'd like to think about first. */ -public interface ObjectSource { - static void allMethods(Generator generator, Object object, BiConsumer> accept) { - for (NamedMethod method : generator.getMethods(object.getClass())) { - accept.accept(object, method); +public interface ObjectSource +{ + static void allMethods( Generator generator, Object object, BiConsumer> accept ) + { + for( NamedMethod method : generator.getMethods( object.getClass() ) ) + { + accept.accept( object, method ); } - if (object instanceof ObjectSource) { - for (Object extra : ((ObjectSource) object).getExtra()) { - for (NamedMethod method : generator.getMethods(extra.getClass())) { - accept.accept(extra, method); + if( object instanceof ObjectSource ) + { + for( Object extra : ((ObjectSource) object).getExtra() ) + { + for( NamedMethod method : generator.getMethods( extra.getClass() ) ) + { + accept.accept( extra, method ); } } } diff --git a/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java b/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java index 07f0c1913..959fbb5d5 100644 --- a/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java +++ b/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java @@ -5,10 +5,6 @@ */ package dan200.computercraft.core.asm; -import java.util.Arrays; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; @@ -16,21 +12,25 @@ import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IDynamicPeripheral; -public interface PeripheralMethod { - Generator GENERATOR = new Generator<>(PeripheralMethod.class, - Arrays.asList(ILuaContext.class, IComputerAccess.class), - m -> (target, context, computer, args) -> TaskCallback.make(context, - () -> TaskCallback.checkUnwrap(m.apply( - target, - context, - computer, - args)))); +import javax.annotation.Nonnull; +import java.util.Arrays; - IntCache DYNAMIC = new IntCache<>(method -> (instance, context, computer, args) -> ((IDynamicPeripheral) instance).callMethod(computer, - context, - method, - args)); +public interface PeripheralMethod +{ + Generator GENERATOR = new Generator<>( PeripheralMethod.class, + Arrays.asList( ILuaContext.class, IComputerAccess.class ), + m -> ( target, context, computer, args ) -> TaskCallback.make( context, + () -> TaskCallback.checkUnwrap( m.apply( + target, + context, + computer, + args ) ) ) ); + + IntCache DYNAMIC = new IntCache<>( method -> ( instance, context, computer, args ) -> ((IDynamicPeripheral) instance).callMethod( computer, + context, + method, + args ) ); @Nonnull - MethodResult apply(@Nonnull Object target, @Nonnull ILuaContext context, @Nonnull IComputerAccess computer, @Nonnull IArguments args) throws LuaException; + MethodResult apply( @Nonnull Object target, @Nonnull ILuaContext context, @Nonnull IComputerAccess computer, @Nonnull IArguments args ) throws LuaException; } diff --git a/src/main/java/dan200/computercraft/core/asm/Reflect.java b/src/main/java/dan200/computercraft/core/asm/Reflect.java index adac4de3d..15e016215 100644 --- a/src/main/java/dan200/computercraft/core/asm/Reflect.java +++ b/src/main/java/dan200/computercraft/core/asm/Reflect.java @@ -5,51 +5,59 @@ */ package dan200.computercraft.core.asm; -import static org.objectweb.asm.Opcodes.ICONST_0; +import dan200.computercraft.ComputerCraft; +import org.objectweb.asm.MethodVisitor; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; +import javax.annotation.Nullable; +import java.lang.reflect.*; import java.nio.ByteBuffer; import java.util.Map; import java.util.Optional; -import javax.annotation.Nullable; +import static org.objectweb.asm.Opcodes.ICONST_0; -import dan200.computercraft.ComputerCraft; -import org.objectweb.asm.MethodVisitor; - -final class Reflect { +final class Reflect +{ static final java.lang.reflect.Type OPTIONAL_IN = Optional.class.getTypeParameters()[0]; - private Reflect() { + private Reflect() + { } @Nullable - static String getLuaName(Class klass) { - if (klass.isPrimitive()) { - if (klass == int.class) { + static String getLuaName( Class klass ) + { + if( klass.isPrimitive() ) + { + if( klass == int.class ) + { return "Int"; } - if (klass == boolean.class) { + if( klass == boolean.class ) + { return "Boolean"; } - if (klass == double.class) { + if( klass == double.class ) + { return "Double"; } - if (klass == long.class) { + if( klass == long.class ) + { return "Long"; } - } else { - if (klass == Map.class) { + } + else + { + if( klass == Map.class ) + { return "Table"; } - if (klass == String.class) { + if( klass == String.class ) + { return "String"; } - if (klass == ByteBuffer.class) { + if( klass == ByteBuffer.class ) + { return "Bytes"; } } @@ -58,30 +66,38 @@ final class Reflect { } @Nullable - static Class getRawType(Method method, Type root, boolean allowParameter) { + static Class getRawType( Method method, Type root, boolean allowParameter ) + { Type underlying = root; - while (true) { - if (underlying instanceof Class) { + while( true ) + { + if( underlying instanceof Class ) + { return (Class) underlying; } - if (underlying instanceof ParameterizedType) { + if( underlying instanceof ParameterizedType ) + { ParameterizedType type = (ParameterizedType) underlying; - if (!allowParameter) { - for (java.lang.reflect.Type arg : type.getActualTypeArguments()) { - if (arg instanceof WildcardType) { + if( !allowParameter ) + { + for( java.lang.reflect.Type arg : type.getActualTypeArguments() ) + { + if( arg instanceof WildcardType ) + { continue; } - if (arg instanceof TypeVariable && ((TypeVariable) arg).getName() - .startsWith("capture#")) { + if( arg instanceof TypeVariable && ((TypeVariable) arg).getName() + .startsWith( "capture#" ) ) + { continue; } - ComputerCraft.log.error("Method {}.{} has generic type {} with non-wildcard argument {}.", - method.getDeclaringClass(), - method.getName(), - root, - arg); + ComputerCraft.log.error( "Method {}.{} has generic type {} with non-wildcard argument {}.", + method.getDeclaringClass(), + method.getName(), + root, + arg ); return null; } } @@ -91,16 +107,20 @@ final class Reflect { continue; } - ComputerCraft.log.error("Method {}.{} has unknown generic type {}.", method.getDeclaringClass(), method.getName(), root); + ComputerCraft.log.error( "Method {}.{} has unknown generic type {}.", method.getDeclaringClass(), method.getName(), root ); return null; } } - static void loadInt(MethodVisitor visitor, int value) { - if (value >= -1 && value <= 5) { - visitor.visitInsn(ICONST_0 + value); - } else { - visitor.visitLdcInsn(value); + static void loadInt( MethodVisitor visitor, int value ) + { + if( value >= -1 && value <= 5 ) + { + visitor.visitInsn( ICONST_0 + value ); + } + else + { + visitor.visitLdcInsn( value ); } } } diff --git a/src/main/java/dan200/computercraft/core/asm/TaskCallback.java b/src/main/java/dan200/computercraft/core/asm/TaskCallback.java index 918710e11..b5c208a29 100644 --- a/src/main/java/dan200/computercraft/core/asm/TaskCallback.java +++ b/src/main/java/dan200/computercraft/core/asm/TaskCallback.java @@ -5,58 +5,66 @@ */ package dan200.computercraft.core.asm; -import java.util.Arrays; +import dan200.computercraft.api.lua.*; import javax.annotation.Nonnull; +import java.util.Arrays; -import dan200.computercraft.api.lua.ILuaCallback; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.ILuaTask; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; - -public final class TaskCallback implements ILuaCallback { - private final MethodResult pull = MethodResult.pullEvent("task_complete", this); +public final class TaskCallback implements ILuaCallback +{ + private final MethodResult pull = MethodResult.pullEvent( "task_complete", this ); private final long task; - private TaskCallback(long task) { + private TaskCallback( long task ) + { this.task = task; } - static Object[] checkUnwrap(MethodResult result) { - if (result.getCallback() != null) { + static Object[] checkUnwrap( MethodResult result ) + { + if( result.getCallback() != null ) + { // Due to how tasks are implemented, we can't currently return a MethodResult. This is an // entirely artificial limitation - we can remove it if it ever becomes an issue. - throw new IllegalStateException("Cannot return MethodResult for mainThread task."); + throw new IllegalStateException( "Cannot return MethodResult for mainThread task." ); } return result.getResult(); } - public static MethodResult make(ILuaContext context, ILuaTask func) throws LuaException { - long task = context.issueMainThreadTask(func); - return new TaskCallback(task).pull; + public static MethodResult make( ILuaContext context, ILuaTask func ) throws LuaException + { + long task = context.issueMainThreadTask( func ); + return new TaskCallback( task ).pull; } @Nonnull @Override - public MethodResult resume(Object[] response) throws LuaException { - if (response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean)) { + public MethodResult resume( Object[] response ) throws LuaException + { + if( response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean) ) + { return this.pull; } - if (((Number) response[1]).longValue() != this.task) { + if( ((Number) response[1]).longValue() != this.task ) + { return this.pull; } - if ((Boolean) response[2]) { + if( (Boolean) response[2] ) + { // Extract the return values from the event and return them - return MethodResult.of(Arrays.copyOfRange(response, 3, response.length)); - } else if (response.length >= 4 && response[3] instanceof String) { + return MethodResult.of( Arrays.copyOfRange( response, 3, response.length ) ); + } + else if( response.length >= 4 && response[3] instanceof String ) + { // Extract the error message from the event and raise it - throw new LuaException((String) response[3]); - } else { - throw new LuaException("error"); + throw new LuaException( (String) response[3] ); + } + else + { + throw new LuaException( "error" ); } } } diff --git a/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java b/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java index 3a75d7428..bea5b44c8 100644 --- a/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java +++ b/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java @@ -11,37 +11,44 @@ import dan200.computercraft.api.lua.ILuaAPI; /** * A wrapper for {@link ILuaAPI}s which cleans up after a {@link ComputerSystem} when the computer is shutdown. */ -final class ApiWrapper implements ILuaAPI { +final class ApiWrapper implements ILuaAPI +{ private final ILuaAPI delegate; private final ComputerSystem system; - ApiWrapper(ILuaAPI delegate, ComputerSystem system) { + ApiWrapper( ILuaAPI delegate, ComputerSystem system ) + { this.delegate = delegate; this.system = system; } @Override - public String[] getNames() { + public String[] getNames() + { return this.delegate.getNames(); } @Override - public void startup() { + public void startup() + { this.delegate.startup(); } @Override - public void update() { + public void update() + { this.delegate.update(); } @Override - public void shutdown() { + public void shutdown() + { this.delegate.shutdown(); this.system.unmountAll(); } - public ILuaAPI getDelegate() { + public ILuaAPI getDelegate() + { return this.delegate; } } diff --git a/src/main/java/dan200/computercraft/core/computer/Computer.java b/src/main/java/dan200/computercraft/core/computer/Computer.java index 534f97596..db70b2e88 100644 --- a/src/main/java/dan200/computercraft/core/computer/Computer.java +++ b/src/main/java/dan200/computercraft/core/computer/Computer.java @@ -6,8 +6,6 @@ package dan200.computercraft.core.computer; -import java.util.concurrent.atomic.AtomicBoolean; - import com.google.common.base.Objects; import dan200.computercraft.api.lua.ILuaAPI; import dan200.computercraft.api.peripheral.IWorkMonitor; @@ -15,6 +13,8 @@ import dan200.computercraft.core.apis.IAPIEnvironment; import dan200.computercraft.core.filesystem.FileSystem; import dan200.computercraft.core.terminal.Terminal; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Represents a computer which may exist in-world or elsewhere. * @@ -28,14 +28,15 @@ import dan200.computercraft.core.terminal.Terminal; *
  • Passes main thread tasks to the {@link MainThreadExecutor}.
  • * */ -public class Computer { +public class Computer +{ private static final int START_DELAY = 50; // Read-only fields about the computer private final IComputerEnvironment m_environment; private final Terminal m_terminal; private final ComputerExecutor executor; private final MainThreadExecutor serverExecutor; - private final Environment internalEnvironment = new Environment(this); + private final Environment internalEnvironment = new Environment( this ); private final AtomicBoolean externalOutputChanged = new AtomicBoolean(); // Various properties of the computer private int m_id; @@ -45,53 +46,64 @@ public class Computer { private boolean startRequested; private int m_ticksSinceStart = -1; - public Computer(IComputerEnvironment environment, Terminal terminal, int id) { + public Computer( IComputerEnvironment environment, Terminal terminal, int id ) + { this.m_id = id; this.m_environment = environment; this.m_terminal = terminal; - this.executor = new ComputerExecutor(this); - this.serverExecutor = new MainThreadExecutor(this); + this.executor = new ComputerExecutor( this ); + this.serverExecutor = new MainThreadExecutor( this ); } - IComputerEnvironment getComputerEnvironment() { + IComputerEnvironment getComputerEnvironment() + { return this.m_environment; } - FileSystem getFileSystem() { + FileSystem getFileSystem() + { return this.executor.getFileSystem(); } - Terminal getTerminal() { + Terminal getTerminal() + { return this.m_terminal; } - public Environment getEnvironment() { + public Environment getEnvironment() + { return this.internalEnvironment; } - public IAPIEnvironment getAPIEnvironment() { + public IAPIEnvironment getAPIEnvironment() + { return this.internalEnvironment; } - public void turnOn() { + public void turnOn() + { this.startRequested = true; } - public void shutdown() { - this.executor.queueStop(false, false); + public void shutdown() + { + this.executor.queueStop( false, false ); } - public void reboot() { - this.executor.queueStop(true, false); + public void reboot() + { + this.executor.queueStop( true, false ); } - public void unload() { - this.executor.queueStop(false, true); + public void unload() + { + this.executor.queueStop( false, true ); } - public void queueEvent(String event, Object[] args) { - this.executor.queueEvent(event, args); + public void queueEvent( String event, Object[] args ) + { + this.executor.queueEvent( event, args ); } /** @@ -100,49 +112,62 @@ public class Computer { * @param runnable The task to run * @return If the task was successfully queued (namely, whether there is space on it). */ - public boolean queueMainThread(Runnable runnable) { - return this.serverExecutor.enqueue(runnable); + public boolean queueMainThread( Runnable runnable ) + { + return this.serverExecutor.enqueue( runnable ); } - public IWorkMonitor getMainThreadMonitor() { + public IWorkMonitor getMainThreadMonitor() + { return this.serverExecutor; } - public int getID() { + public int getID() + { return this.m_id; } - public void setID(int id) { + public void setID( int id ) + { this.m_id = id; } - public int assignID() { - if (this.m_id < 0) { + public int assignID() + { + if( this.m_id < 0 ) + { this.m_id = this.m_environment.assignNewID(); } return this.m_id; } - public String getLabel() { + public String getLabel() + { return this.m_label; } - public void setLabel(String label) { - if (!Objects.equal(label, this.m_label)) { + public void setLabel( String label ) + { + if( !Objects.equal( label, this.m_label ) ) + { this.m_label = label; - this.externalOutputChanged.set(true); + this.externalOutputChanged.set( true ); } } - public void tick() { + public void tick() + { // We keep track of the number of ticks since the last start, only - if (this.m_ticksSinceStart >= 0 && this.m_ticksSinceStart <= START_DELAY) { + if( this.m_ticksSinceStart >= 0 && this.m_ticksSinceStart <= START_DELAY ) + { this.m_ticksSinceStart++; } - if (this.startRequested && (this.m_ticksSinceStart < 0 || this.m_ticksSinceStart > START_DELAY)) { + if( this.startRequested && (this.m_ticksSinceStart < 0 || this.m_ticksSinceStart > START_DELAY) ) + { this.startRequested = false; - if (!this.executor.isOn()) { + if( !this.executor.isOn() ) + { this.m_ticksSinceStart = 0; this.executor.queueStart(); } @@ -154,35 +179,42 @@ public class Computer { this.internalEnvironment.tick(); // Propagate the environment's output to the world. - if (this.internalEnvironment.updateOutput()) { - this.externalOutputChanged.set(true); + if( this.internalEnvironment.updateOutput() ) + { + this.externalOutputChanged.set( true ); } // Set output changed if the terminal has changed from blinking to not boolean blinking = this.m_terminal.getCursorBlink() && this.m_terminal.getCursorX() >= 0 && this.m_terminal.getCursorX() < this.m_terminal.getWidth() && this.m_terminal.getCursorY() >= 0 && this.m_terminal.getCursorY() < this.m_terminal.getHeight(); - if (blinking != this.m_blinking) { + if( blinking != this.m_blinking ) + { this.m_blinking = blinking; - this.externalOutputChanged.set(true); + this.externalOutputChanged.set( true ); } } - void markChanged() { - this.externalOutputChanged.set(true); + void markChanged() + { + this.externalOutputChanged.set( true ); } - public boolean pollAndResetChanged() { - return this.externalOutputChanged.getAndSet(false); + public boolean pollAndResetChanged() + { + return this.externalOutputChanged.getAndSet( false ); } - public boolean isBlinking() { + public boolean isBlinking() + { return this.isOn() && this.m_blinking; } - public boolean isOn() { + public boolean isOn() + { return this.executor.isOn(); } - public void addApi(ILuaAPI api) { - this.executor.addApi(api); + public void addApi( ILuaAPI api ) + { + this.executor.addApi( api ); } } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java index 6d4f8fe97..bb3b6681e 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java @@ -6,29 +6,12 @@ package dan200.computercraft.core.computer; -import java.io.InputStream; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.ReentrantLock; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.lua.ILuaAPI; import dan200.computercraft.api.lua.ILuaAPIFactory; -import dan200.computercraft.core.apis.ApiFactories; -import dan200.computercraft.core.apis.FSAPI; -import dan200.computercraft.core.apis.HTTPAPI; -import dan200.computercraft.core.apis.OSAPI; -import dan200.computercraft.core.apis.PeripheralAPI; -import dan200.computercraft.core.apis.RedstoneAPI; -import dan200.computercraft.core.apis.TermAPI; +import dan200.computercraft.core.apis.*; import dan200.computercraft.core.filesystem.FileSystem; import dan200.computercraft.core.filesystem.FileSystemException; import dan200.computercraft.core.lua.CobaltLuaMachine; @@ -39,6 +22,16 @@ import dan200.computercraft.core.tracking.Tracking; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.IoUtil; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.InputStream; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantLock; + /** * The main task queue and executor for a single computer. This handles turning on and off a computer, as well as running events. * @@ -55,7 +48,8 @@ import dan200.computercraft.shared.util.IoUtil; * One final responsibility for the executor is calling {@link ILuaAPI#update()} every tick, via the {@link #tick()} method. This should only be called when * the computer is actually on ({@link #isOn}). */ -final class ComputerExecutor { +final class ComputerExecutor +{ private static final int QUEUE_LIMIT = 256; final TimeoutState timeout = new TimeoutState(); /** @@ -88,7 +82,7 @@ final class ComputerExecutor { * * Note, this should be empty if this computer is off - it is cleared on shutdown and when turning on again. */ - private final Queue eventQueue = new ArrayDeque<>(4); + private final Queue eventQueue = new ArrayDeque<>( 4 ); /** * Determines if this executor is present within {@link ComputerThread}. * @@ -143,7 +137,8 @@ final class ComputerExecutor { private boolean closed; private IWritableMount rootMount; - ComputerExecutor(Computer computer) { + ComputerExecutor( Computer computer ) + { // Ensure the computer thread is running as required. ComputerThread.start(); @@ -152,44 +147,53 @@ final class ComputerExecutor { Environment environment = computer.getEnvironment(); // Add all default APIs to the loaded list. - this.apis.add(new TermAPI(environment)); - this.apis.add(new RedstoneAPI(environment)); - this.apis.add(new FSAPI(environment)); - this.apis.add(new PeripheralAPI(environment)); - this.apis.add(new OSAPI(environment)); - if (ComputerCraft.httpEnabled) { - this.apis.add(new HTTPAPI(environment)); + this.apis.add( new TermAPI( environment ) ); + this.apis.add( new RedstoneAPI( environment ) ); + this.apis.add( new FSAPI( environment ) ); + this.apis.add( new PeripheralAPI( environment ) ); + this.apis.add( new OSAPI( environment ) ); + if( ComputerCraft.httpEnabled ) + { + this.apis.add( new HTTPAPI( environment ) ); } // Load in the externally registered APIs. - for (ILuaAPIFactory factory : ApiFactories.getAll()) { - ComputerSystem system = new ComputerSystem(environment); - ILuaAPI api = factory.create(system); - if (api != null) { - this.apis.add(new ApiWrapper(api, system)); + for( ILuaAPIFactory factory : ApiFactories.getAll() ) + { + ComputerSystem system = new ComputerSystem( environment ); + ILuaAPI api = factory.create( system ); + if( api != null ) + { + this.apis.add( new ApiWrapper( api, system ) ); } } } - boolean isOn() { + boolean isOn() + { return this.isOn; } - FileSystem getFileSystem() { + FileSystem getFileSystem() + { return this.fileSystem; } - void addApi(ILuaAPI api) { - this.apis.add(api); + void addApi( ILuaAPI api ) + { + this.apis.add( api ); } /** * Schedule this computer to be started if not already on. */ - void queueStart() { - synchronized (this.queueLock) { + void queueStart() + { + synchronized( this.queueLock ) + { // We should only schedule a start if we're not currently on and there's turn on. - if (this.closed || this.isOn || this.command != null) { + if( this.closed || this.isOn || this.command != null ) + { return; } @@ -201,10 +205,13 @@ final class ComputerExecutor { /** * Add this executor to the {@link ComputerThread} if not already there. */ - private void enqueue() { - synchronized (this.queueLock) { - if (!this.onComputerQueue) { - ComputerThread.queue(this); + private void enqueue() + { + synchronized( this.queueLock ) + { + if( !this.onComputerQueue ) + { + ComputerThread.queue( this ); } } } @@ -213,12 +220,15 @@ final class ComputerExecutor { * Schedule this computer to be stopped if not already on. * * @param reboot Reboot the computer after stopping - * @param close Close the computer after stopping. + * @param close Close the computer after stopping. * @see #closed */ - void queueStop(boolean reboot, boolean close) { - synchronized (this.queueLock) { - if (this.closed) { + void queueStop( boolean reboot, boolean close ) + { + synchronized( this.queueLock ) + { + if( this.closed ) + { return; } this.closed = close; @@ -226,9 +236,11 @@ final class ComputerExecutor { StateCommand newCommand = reboot ? StateCommand.REBOOT : StateCommand.SHUTDOWN; // We should only schedule a stop if we're currently on and there's no shutdown pending. - if (!this.isOn || this.command != null) { + if( !this.isOn || this.command != null ) + { // If we're closing, set the command just in case. - if (close) { + if( close ) + { this.command = newCommand; } return; @@ -242,18 +254,23 @@ final class ComputerExecutor { /** * Abort this whole computer due to a timeout. This will immediately destroy the Lua machine, and then schedule a shutdown. */ - void abort() { + void abort() + { ILuaMachine machine = this.machine; - if (machine != null) { + if( machine != null ) + { machine.close(); } - synchronized (this.queueLock) { - if (this.closed) { + synchronized( this.queueLock ) + { + if( this.closed ) + { return; } this.command = StateCommand.ABORT; - if (this.isOn) { + if( this.isOn ) + { this.enqueue(); } } @@ -263,23 +280,27 @@ final class ComputerExecutor { * Queue an event if the computer is on. * * @param event The event's name - * @param args The event's arguments + * @param args The event's arguments */ - void queueEvent(@Nonnull String event, @Nullable Object[] args) { + void queueEvent( @Nonnull String event, @Nullable Object[] args ) + { // Events should be skipped if we're not on. - if (!this.isOn) { + if( !this.isOn ) + { return; } - synchronized (this.queueLock) { + synchronized( this.queueLock ) + { // And if we've got some command in the pipeline, then don't queue events - they'll // probably be disposed of anyway. // We also limit the number of events which can be queued. - if (this.closed || this.command != null || this.eventQueue.size() >= QUEUE_LIMIT) { + if( this.closed || this.command != null || this.eventQueue.size() >= QUEUE_LIMIT ) + { return; } - this.eventQueue.offer(new Event(event, args)); + this.eventQueue.offer( new Event( event, args ) ); this.enqueue(); } } @@ -287,20 +308,27 @@ final class ComputerExecutor { /** * Update the internals of the executor. */ - void tick() { - if (this.isOn && this.isOnLock.tryLock()) { + void tick() + { + if( this.isOn && this.isOnLock.tryLock() ) + { // This horrific structure means we don't try to update APIs while the state is being changed // (and so they may be running startup/shutdown). // We use tryLock here, as it has minimal delay, and it doesn't matter if we miss an advance at the // beginning or end of a computer's lifetime. - try { - if (this.isOn) { + try + { + if( this.isOn ) + { // Advance our APIs. - for (ILuaAPI api : this.apis) { + for( ILuaAPI api : this.apis ) + { api.update(); } } - } finally { + } + finally + { this.isOnLock.unlock(); } } @@ -309,7 +337,8 @@ final class ComputerExecutor { /** * Called before calling {@link #work()}, setting up any important state. */ - void beforeWork() { + void beforeWork() + { this.vRuntimeStart = System.nanoTime(); this.timeout.startTimer(); } @@ -319,28 +348,36 @@ final class ComputerExecutor { * * @return If we have more work to do. */ - boolean afterWork() { - if (this.interruptedEvent) { + boolean afterWork() + { + if( this.interruptedEvent ) + { this.timeout.pauseTimer(); - } else { + } + else + { this.timeout.stopTimer(); } - Tracking.addTaskTiming(this.getComputer(), this.timeout.nanoCurrent()); + Tracking.addTaskTiming( this.getComputer(), this.timeout.nanoCurrent() ); - if (this.interruptedEvent) { + if( this.interruptedEvent ) + { return true; } - synchronized (this.queueLock) { - if (this.eventQueue.isEmpty() && this.command == null) { + synchronized( this.queueLock ) + { + if( this.eventQueue.isEmpty() && this.command == null ) + { return this.onComputerQueue = false; } return true; } } - Computer getComputer() { + Computer getComputer() + { return this.computer; } @@ -353,24 +390,30 @@ final class ComputerExecutor { * @see #command * @see #eventQueue */ - void work() throws InterruptedException { - if (this.interruptedEvent) { + void work() throws InterruptedException + { + if( this.interruptedEvent ) + { this.interruptedEvent = false; - if (this.machine != null) { - this.resumeMachine(null, null); + if( this.machine != null ) + { + this.resumeMachine( null, null ); return; } } StateCommand command; Event event = null; - synchronized (this.queueLock) { + synchronized( this.queueLock ) + { command = this.command; this.command = null; // If we've no command, pull something from the event queue instead. - if (command == null) { - if (!this.isOn) { + if( command == null ) + { + if( !this.isOn ) + { // We're not on and had no command, but we had work queued. This should never happen, so clear // the event queue just in case. this.eventQueue.clear(); @@ -381,86 +424,102 @@ final class ComputerExecutor { } } - if (command != null) { - switch (command) { - case TURN_ON: - if (this.isOn) { - return; - } - this.turnOn(); - break; + if( command != null ) + { + switch( command ) + { + case TURN_ON: + if( this.isOn ) + { + return; + } + this.turnOn(); + break; - case SHUTDOWN: + case SHUTDOWN: - if (!this.isOn) { - return; - } - this.computer.getTerminal() - .reset(); - this.shutdown(); - break; + if( !this.isOn ) + { + return; + } + this.computer.getTerminal() + .reset(); + this.shutdown(); + break; - case REBOOT: - if (!this.isOn) { - return; - } - this.computer.getTerminal() - .reset(); - this.shutdown(); + case REBOOT: + if( !this.isOn ) + { + return; + } + this.computer.getTerminal() + .reset(); + this.shutdown(); - this.computer.turnOn(); - break; + this.computer.turnOn(); + break; - case ABORT: - if (!this.isOn) { - return; - } - this.displayFailure("Error running computer", TimeoutState.ABORT_MESSAGE); - this.shutdown(); - break; + case ABORT: + if( !this.isOn ) + { + return; + } + this.displayFailure( "Error running computer", TimeoutState.ABORT_MESSAGE ); + this.shutdown(); + break; } - } else if (event != null) { - this.resumeMachine(event.name, event.args); + } + else if( event != null ) + { + this.resumeMachine( event.name, event.args ); } } - private void resumeMachine(String event, Object[] args) throws InterruptedException { - MachineResult result = this.machine.handleEvent(event, args); + private void resumeMachine( String event, Object[] args ) throws InterruptedException + { + MachineResult result = this.machine.handleEvent( event, args ); this.interruptedEvent = result.isPause(); - if (!result.isError()) { + if( !result.isError() ) + { return; } - this.displayFailure("Error running computer", result.getMessage()); + this.displayFailure( "Error running computer", result.getMessage() ); this.shutdown(); } - private void turnOn() throws InterruptedException { + private void turnOn() throws InterruptedException + { this.isOnLock.lockInterruptibly(); - try { + try + { // Reset the terminal and event queue this.computer.getTerminal() - .reset(); + .reset(); this.interruptedEvent = false; - synchronized (this.queueLock) { + synchronized( this.queueLock ) + { this.eventQueue.clear(); } // Init filesystem - if ((this.fileSystem = this.createFileSystem()) == null) { + if( (this.fileSystem = this.createFileSystem()) == null ) + { this.shutdown(); return; } // Init APIs this.computer.getEnvironment() - .reset(); - for (ILuaAPI api : this.apis) { + .reset(); + for( ILuaAPI api : this.apis ) + { api.startup(); } // Init lua - if ((this.machine = this.createLuaMachine()) == null) { + if( (this.machine = this.createLuaMachine()) == null ) + { this.shutdown(); return; } @@ -468,159 +527,192 @@ final class ComputerExecutor { // Initialisation has finished, so let's mark ourselves as on. this.isOn = true; this.computer.markChanged(); - } finally { + } + finally + { this.isOnLock.unlock(); } // Now actually start the computer, now that everything is set up. - this.resumeMachine(null, null); + this.resumeMachine( null, null ); } - private void shutdown() throws InterruptedException { + private void shutdown() throws InterruptedException + { this.isOnLock.lockInterruptibly(); - try { + try + { this.isOn = false; this.interruptedEvent = false; - synchronized (this.queueLock) { + synchronized( this.queueLock ) + { this.eventQueue.clear(); } // Shutdown Lua machine - if (this.machine != null) { + if( this.machine != null ) + { this.machine.close(); this.machine = null; } // Shutdown our APIs - for (ILuaAPI api : this.apis) { + for( ILuaAPI api : this.apis ) + { api.shutdown(); } this.computer.getEnvironment() - .reset(); + .reset(); // Unload filesystem - if (this.fileSystem != null) { + if( this.fileSystem != null ) + { this.fileSystem.close(); this.fileSystem = null; } this.computer.getEnvironment() - .resetOutput(); + .resetOutput(); this.computer.markChanged(); - } finally { + } + finally + { this.isOnLock.unlock(); } } - private void displayFailure(String message, String extra) { + private void displayFailure( String message, String extra ) + { Terminal terminal = this.computer.getTerminal(); boolean colour = this.computer.getComputerEnvironment() - .isColour(); + .isColour(); terminal.reset(); // Display our primary error message - if (colour) { - terminal.setTextColour(15 - Colour.RED.ordinal()); + if( colour ) + { + terminal.setTextColour( 15 - Colour.RED.ordinal() ); } - terminal.write(message); + terminal.write( message ); - if (extra != null) { + if( extra != null ) + { // Display any additional information. This generally comes from the Lua Machine, such as compilation or // runtime errors. - terminal.setCursorPos(0, terminal.getCursorY() + 1); - terminal.write(extra); + terminal.setCursorPos( 0, terminal.getCursorY() + 1 ); + terminal.write( extra ); } // And display our generic "CC may be installed incorrectly" message. - terminal.setCursorPos(0, terminal.getCursorY() + 1); - if (colour) { - terminal.setTextColour(15 - Colour.WHITE.ordinal()); + terminal.setCursorPos( 0, terminal.getCursorY() + 1 ); + if( colour ) + { + terminal.setTextColour( 15 - Colour.WHITE.ordinal() ); } - terminal.write("ComputerCraft may be installed incorrectly"); + terminal.write( "ComputerCraft may be installed incorrectly" ); } - private FileSystem createFileSystem() { + private FileSystem createFileSystem() + { FileSystem filesystem = null; - try { - filesystem = new FileSystem("hdd", this.getRootMount()); + try + { + filesystem = new FileSystem( "hdd", this.getRootMount() ); IMount romMount = this.getRomMount(); - if (romMount == null) { - this.displayFailure("Cannot mount ROM", null); + if( romMount == null ) + { + this.displayFailure( "Cannot mount ROM", null ); return null; } - filesystem.mount("rom", "rom", romMount); + filesystem.mount( "rom", "rom", romMount ); return filesystem; - } catch (FileSystemException e) { - if (filesystem != null) { + } + catch( FileSystemException e ) + { + if( filesystem != null ) + { filesystem.close(); } - ComputerCraft.log.error("Cannot mount computer filesystem", e); + ComputerCraft.log.error( "Cannot mount computer filesystem", e ); - this.displayFailure("Cannot mount computer system", null); + this.displayFailure( "Cannot mount computer system", null ); return null; } } - private ILuaMachine createLuaMachine() { + private ILuaMachine createLuaMachine() + { // Load the bios resource InputStream biosStream = null; - try { + try + { biosStream = this.computer.getComputerEnvironment() - .createResourceFile("computercraft", "lua/bios.lua"); - } catch (Exception ignored) { + .createResourceFile( "computercraft", "lua/bios.lua" ); + } + catch( Exception ignored ) + { } - if (biosStream == null) { - this.displayFailure("Error loading bios.lua", null); + if( biosStream == null ) + { + this.displayFailure( "Error loading bios.lua", null ); return null; } // Create the lua machine - ILuaMachine machine = new CobaltLuaMachine(this.computer, this.timeout); + ILuaMachine machine = new CobaltLuaMachine( this.computer, this.timeout ); // Add the APIs. We unwrap them (yes, this is horrible) to get access to the underlying object. - for (ILuaAPI api : this.apis) { - machine.addAPI(api instanceof ApiWrapper ? ((ApiWrapper) api).getDelegate() : api); + for( ILuaAPI api : this.apis ) + { + machine.addAPI( api instanceof ApiWrapper ? ((ApiWrapper) api).getDelegate() : api ); } // Start the machine running the bios resource - MachineResult result = machine.loadBios(biosStream); - IoUtil.closeQuietly(biosStream); + MachineResult result = machine.loadBios( biosStream ); + IoUtil.closeQuietly( biosStream ); - if (result.isError()) { + if( result.isError() ) + { machine.close(); - this.displayFailure("Error loading bios.lua", result.getMessage()); + this.displayFailure( "Error loading bios.lua", result.getMessage() ); return null; } return machine; } - private IWritableMount getRootMount() { - if (this.rootMount == null) { + private IWritableMount getRootMount() + { + if( this.rootMount == null ) + { this.rootMount = this.computer.getComputerEnvironment() - .createSaveDirMount("computer/" + this.computer.assignID(), this.computer.getComputerEnvironment() - .getComputerSpaceLimit()); + .createSaveDirMount( "computer/" + this.computer.assignID(), this.computer.getComputerEnvironment() + .getComputerSpaceLimit() ); } return this.rootMount; } - private IMount getRomMount() { + private IMount getRomMount() + { return this.computer.getComputerEnvironment() - .createResourceMount("computercraft", "lua/rom"); + .createResourceMount( "computercraft", "lua/rom" ); } - private enum StateCommand { + private enum StateCommand + { TURN_ON, SHUTDOWN, REBOOT, ABORT, } - private static final class Event { + private static final class Event + { final String name; final Object[] args; - private Event(String name, Object[] args) { + private Event( String name, Object[] args ) + { this.name = name; this.args = args; } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerSide.java b/src/main/java/dan200/computercraft/core/computer/ComputerSide.java index ea80874d5..fbc4b054e 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerSide.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerSide.java @@ -12,8 +12,9 @@ import javax.annotation.Nullable; /** * A side on a computer. Unlike {@link Direction}, this is relative to the direction the computer is facing.. */ -public enum ComputerSide { - BOTTOM("bottom"), TOP("top"), BACK("back"), FRONT("front"), RIGHT("right"), LEFT("left"); +public enum ComputerSide +{ + BOTTOM( "bottom" ), TOP( "top" ), BACK( "back" ), FRONT( "front" ), RIGHT( "right" ), LEFT( "left" ); public static final String[] NAMES = new String[] { "bottom", @@ -30,19 +31,24 @@ public enum ComputerSide { private final String name; - ComputerSide(String name) { + ComputerSide( String name ) + { this.name = name; } @Nonnull - public static ComputerSide valueOf(int side) { + public static ComputerSide valueOf( int side ) + { return VALUES[side]; } @Nullable - public static ComputerSide valueOfInsensitive(@Nonnull String name) { - for (ComputerSide side : VALUES) { - if (side.name.equalsIgnoreCase(name)) { + public static ComputerSide valueOfInsensitive( @Nonnull String name ) + { + for( ComputerSide side : VALUES ) + { + if( side.name.equalsIgnoreCase( name ) ) + { return side; } } @@ -50,7 +56,8 @@ public enum ComputerSide { return null; } - public String getName() { + public String getName() + { return this.name; } } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java b/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java index 5773e5b07..bdff606db 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java @@ -6,12 +6,6 @@ package dan200.computercraft.core.computer; -import java.util.Collections; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.filesystem.IFileSystem; import dan200.computercraft.api.lua.IComputerSystem; import dan200.computercraft.api.lua.ILuaAPIFactory; @@ -21,6 +15,11 @@ import dan200.computercraft.core.apis.ComputerAccess; import dan200.computercraft.core.apis.IAPIEnvironment; import dan200.computercraft.core.filesystem.FileSystem; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.Map; + /** * Implementation of {@link IComputerAccess}/{@link IComputerSystem} for usage by externally registered APIs. * @@ -28,43 +27,50 @@ import dan200.computercraft.core.filesystem.FileSystem; * @see ILuaAPIFactory * @see ApiWrapper */ -public class ComputerSystem extends ComputerAccess implements IComputerSystem { +public class ComputerSystem extends ComputerAccess implements IComputerSystem +{ private final IAPIEnvironment environment; - ComputerSystem(IAPIEnvironment environment) { - super(environment); + ComputerSystem( IAPIEnvironment environment ) + { + super( environment ); this.environment = environment; } @Nonnull @Override - public String getAttachmentName() { + public String getAttachmentName() + { return "computer"; } @Nonnull @Override - public Map getAvailablePeripherals() { + public Map getAvailablePeripherals() + { // TODO: Should this return peripherals on the current computer? return Collections.emptyMap(); } @Nullable @Override - public IPeripheral getAvailablePeripheral(@Nonnull String name) { + public IPeripheral getAvailablePeripheral( @Nonnull String name ) + { return null; } @Nullable @Override - public IFileSystem getFileSystem() { + public IFileSystem getFileSystem() + { FileSystem fs = this.environment.getFileSystem(); return fs == null ? null : fs.getMountWrapper(); } @Nullable @Override - public String getLabel() { + public String getLabel() + { return this.environment.getLabel(); } } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java index ccebc9e2c..135efd9b0 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java @@ -6,9 +6,11 @@ package dan200.computercraft.core.computer; -import static dan200.computercraft.core.computer.TimeoutState.ABORT_TIMEOUT; -import static dan200.computercraft.core.computer.TimeoutState.TIMEOUT; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.util.ThreadUtils; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.TreeSet; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; @@ -17,11 +19,8 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.util.ThreadUtils; +import static dan200.computercraft.core.computer.TimeoutState.ABORT_TIMEOUT; +import static dan200.computercraft.core.computer.TimeoutState.TIMEOUT; /** * Responsible for running all tasks from a {@link Computer}. @@ -44,7 +43,8 @@ import dan200.computercraft.shared.util.ThreadUtils; * @see TimeoutState For how hard timeouts are handled. * @see ComputerExecutor For how computers actually do execution. */ -public final class ComputerThread { +public final class ComputerThread +{ /** * How often the computer thread monitor should run, in milliseconds. * @@ -57,7 +57,7 @@ public final class ComputerThread { * * An average tick takes 50ms, and so we ideally need to have handled a couple of events within that window in order to have a perceived low latency. */ - private static final long DEFAULT_LATENCY = TimeUnit.MILLISECONDS.toNanos(50); + private static final long DEFAULT_LATENCY = TimeUnit.MILLISECONDS.toNanos( 50 ); /** * The minimum value that {@link #DEFAULT_LATENCY} can have when scaled. @@ -65,7 +65,7 @@ public final class ComputerThread { * From statistics gathered on SwitchCraft, almost all machines will execute under 15ms, 75% under 1.5ms, with the mean being about 3ms. Most computers * shouldn't be too impacted with having such a short period to execute in. */ - private static final long DEFAULT_MIN_PERIOD = TimeUnit.MILLISECONDS.toNanos(5); + private static final long DEFAULT_MIN_PERIOD = TimeUnit.MILLISECONDS.toNanos( 5 ); /** * The maximum number of tasks before we have to start scaling latency linearly. @@ -81,19 +81,21 @@ public final class ComputerThread { /** * Active queues to execute. */ - private static final TreeSet computerQueue = new TreeSet<>((a, b) -> { - if (a == b) { + private static final TreeSet computerQueue = new TreeSet<>( ( a, b ) -> { + if( a == b ) + { return 0; // Should never happen, but let's be consistent here } long at = a.virtualRuntime, bt = b.virtualRuntime; - if (at == bt) { - return Integer.compare(a.hashCode(), b.hashCode()); + if( at == bt ) + { + return Integer.compare( a.hashCode(), b.hashCode() ); } return at < bt ? -1 : 1; - }); - private static final ThreadFactory monitorFactory = ThreadUtils.factory("Computer-Monitor"); - private static final ThreadFactory runnerFactory = ThreadUtils.factory("Computer-Runner"); + } ); + private static final ThreadFactory monitorFactory = ThreadUtils.factory( "Computer-Monitor" ); + private static final ThreadFactory runnerFactory = ThreadUtils.factory( "Computer-Runner" ); /** * Whether the computer thread system is currently running. */ @@ -118,36 +120,43 @@ public final class ComputerThread { /** * Start the computer thread. */ - static void start() { - synchronized (threadLock) { + static void start() + { + synchronized( threadLock ) + { running = true; - if (runners == null) { + if( runners == null ) + { // TODO: Change the runners length on config reloads runners = new TaskRunner[ComputerCraft.computerThreads]; // latency and minPeriod are scaled by 1 + floor(log2(threads)). We can afford to execute tasks for // longer when executing on more than one thread. - long factor = 64 - Long.numberOfLeadingZeros(runners.length); + long factor = 64 - Long.numberOfLeadingZeros( runners.length ); latency = DEFAULT_LATENCY * factor; minPeriod = DEFAULT_MIN_PERIOD * factor; } - for (int i = 0; i < runners.length; i++) { + for( int i = 0; i < runners.length; i++ ) + { TaskRunner runner = runners[i]; - if (runner == null || runner.owner == null || !runner.owner.isAlive()) { + if( runner == null || runner.owner == null || !runner.owner.isAlive() ) + { // Mark the old runner as dead, just in case. - if (runner != null) { + if( runner != null ) + { runner.running = false; } // And start a new runner - runnerFactory.newThread(runners[i] = new TaskRunner()) - .start(); + runnerFactory.newThread( runners[i] = new TaskRunner() ) + .start(); } } - if (monitor == null || !monitor.isAlive()) { - (monitor = monitorFactory.newThread(new Monitor())).start(); + if( monitor == null || !monitor.isAlive() ) + { + (monitor = monitorFactory.newThread( new Monitor() )).start(); } } } @@ -155,17 +164,23 @@ public final class ComputerThread { /** * Attempt to stop the computer thread. This interrupts each runner, and clears the task queue. */ - public static void stop() { - synchronized (threadLock) { + public static void stop() + { + synchronized( threadLock ) + { running = false; - if (runners != null) { - for (TaskRunner runner : runners) { - if (runner == null) { + if( runners != null ) + { + for( TaskRunner runner : runners ) + { + if( runner == null ) + { continue; } runner.running = false; - if (runner.owner != null) { + if( runner.owner != null ) + { runner.owner.interrupt(); } } @@ -173,9 +188,12 @@ public final class ComputerThread { } computerLock.lock(); - try { + try + { computerQueue.clear(); - } finally { + } + finally + { computerLock.unlock(); } } @@ -187,34 +205,42 @@ public final class ComputerThread { * * @param executor The computer to execute work on. */ - static void queue(@Nonnull ComputerExecutor executor) { + static void queue( @Nonnull ComputerExecutor executor ) + { computerLock.lock(); - try { - if (executor.onComputerQueue) { - throw new IllegalStateException("Cannot queue already queued executor"); + try + { + if( executor.onComputerQueue ) + { + throw new IllegalStateException( "Cannot queue already queued executor" ); } executor.onComputerQueue = true; - updateRuntimes(null); + updateRuntimes( null ); // We're not currently on the queue, so update its current execution time to // ensure its at least as high as the minimum. long newRuntime = minimumVirtualRuntime; - if (executor.virtualRuntime == 0) { + if( executor.virtualRuntime == 0 ) + { // Slow down new computers a little bit. newRuntime += scaledPeriod(); - } else { + } + else + { // Give a small boost to computers which have slept a little. newRuntime -= latency / 2; } - executor.virtualRuntime = Math.max(newRuntime, executor.virtualRuntime); + executor.virtualRuntime = Math.max( newRuntime, executor.virtualRuntime ); // Add to the queue, and signal the workers. - computerQueue.add(executor); + computerQueue.add( executor ); hasWork.signal(); - } finally { + } + finally + { computerLock.unlock(); } } @@ -228,11 +254,13 @@ public final class ComputerThread { * * @param current The machine which we updating runtimes from. */ - private static void updateRuntimes(@Nullable ComputerExecutor current) { + private static void updateRuntimes( @Nullable ComputerExecutor current ) + { long minRuntime = Long.MAX_VALUE; // If we've a task on the queue, use that as our base time. - if (!computerQueue.isEmpty()) { + if( !computerQueue.isEmpty() ) + { minRuntime = computerQueue.first().virtualRuntime; } @@ -240,29 +268,35 @@ public final class ComputerThread { long now = System.nanoTime(); int tasks = 1 + computerQueue.size(); TaskRunner[] currentRunners = runners; - if (currentRunners != null) { - for (TaskRunner runner : currentRunners) { - if (runner == null) { + if( currentRunners != null ) + { + for( TaskRunner runner : currentRunners ) + { + if( runner == null ) + { continue; } ComputerExecutor executor = runner.currentExecutor.get(); - if (executor == null) { + if( executor == null ) + { continue; } // We do two things here: first we update the task's virtual runtime based on when we // last checked, and then we check the minimum. - minRuntime = Math.min(minRuntime, executor.virtualRuntime += (now - executor.vRuntimeStart) / tasks); + minRuntime = Math.min( minRuntime, executor.virtualRuntime += (now - executor.vRuntimeStart) / tasks ); executor.vRuntimeStart = now; } } // And update the most recently executed one (if set). - if (current != null) { - minRuntime = Math.min(minRuntime, current.virtualRuntime += (now - current.vRuntimeStart) / tasks); + if( current != null ) + { + minRuntime = Math.min( minRuntime, current.virtualRuntime += (now - current.vRuntimeStart) / tasks ); } - if (minRuntime > minimumVirtualRuntime && minRuntime < Long.MAX_VALUE) { + if( minRuntime > minimumVirtualRuntime && minRuntime < Long.MAX_VALUE ) + { minimumVirtualRuntime = minRuntime; } } @@ -275,7 +309,8 @@ public final class ComputerThread { * @see #DEFAULT_MIN_PERIOD * @see #LATENCY_MAX_TASKS */ - static long scaledPeriod() { + static long scaledPeriod() + { // +1 to include the current task int count = 1 + computerQueue.size(); return count < LATENCY_MAX_TASKS ? latency / count : minPeriod; @@ -284,34 +319,40 @@ public final class ComputerThread { /** * Ensure the "currently working" state of the executor is reset, the timings are updated, and then requeue the executor if needed. * - * @param runner The runner this task was on. + * @param runner The runner this task was on. * @param executor The executor to requeue */ - private static void afterWork(TaskRunner runner, ComputerExecutor executor) { + private static void afterWork( TaskRunner runner, ComputerExecutor executor ) + { // Clear the executor's thread. - Thread currentThread = executor.executingThread.getAndSet(null); - if (currentThread != runner.owner) { + Thread currentThread = executor.executingThread.getAndSet( null ); + if( currentThread != runner.owner ) + { ComputerCraft.log.error( "Expected computer #{} to be running on {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.", executor.getComputer() - .getID(), + .getID(), runner.owner.getName(), - currentThread == null ? "nothing" : currentThread.getName()); + currentThread == null ? "nothing" : currentThread.getName() ); } computerLock.lock(); - try { - updateRuntimes(executor); + try + { + updateRuntimes( executor ); // If we've no more tasks, just return. - if (!executor.afterWork()) { + if( !executor.afterWork() ) + { return; } // Otherwise, add to the queue, and signal any waiting workers. - computerQueue.add(executor); + computerQueue.add( executor ); hasWork.signal(); - } finally { + } + finally + { computerLock.unlock(); } } @@ -321,36 +362,41 @@ public final class ComputerThread { * * @return If we have work queued up. */ - static boolean hasPendingWork() { + static boolean hasPendingWork() + { return !computerQueue.isEmpty(); } - private static void timeoutTask(ComputerExecutor executor, Thread thread, long time) { - if (!ComputerCraft.logComputerErrors) { + private static void timeoutTask( ComputerExecutor executor, Thread thread, long time ) + { + if( !ComputerCraft.logComputerErrors ) + { return; } - StringBuilder builder = new StringBuilder().append("Terminating computer #") - .append(executor.getComputer() - .getID()) - .append(" due to timeout (running for ") - .append(time * 1e-9) - .append(" seconds). This is NOT a bug, but may mean a computer is misbehaving. ") - .append(thread.getName()) - .append(" is currently ") - .append(thread.getState()); - Object blocking = LockSupport.getBlocker(thread); - if (blocking != null) { - builder.append("\n on ") - .append(blocking); + StringBuilder builder = new StringBuilder().append( "Terminating computer #" ) + .append( executor.getComputer() + .getID() ) + .append( " due to timeout (running for " ) + .append( time * 1e-9 ) + .append( " seconds). This is NOT a bug, but may mean a computer is misbehaving. " ) + .append( thread.getName() ) + .append( " is currently " ) + .append( thread.getState() ); + Object blocking = LockSupport.getBlocker( thread ); + if( blocking != null ) + { + builder.append( "\n on " ) + .append( blocking ); } - for (StackTraceElement element : thread.getStackTrace()) { - builder.append("\n at ") - .append(element); + for( StackTraceElement element : thread.getStackTrace() ) + { + builder.append( "\n at " ) + .append( element ); } - ComputerCraft.log.warn(builder.toString()); + ComputerCraft.log.warn( builder.toString() ); } /** @@ -358,36 +404,46 @@ public final class ComputerThread { * * @see TimeoutState */ - private static final class Monitor implements Runnable { + private static final class Monitor implements Runnable + { @Override - public void run() { - try { - while (true) { - Thread.sleep(MONITOR_WAKEUP); + public void run() + { + try + { + while( true ) + { + Thread.sleep( MONITOR_WAKEUP ); TaskRunner[] currentRunners = ComputerThread.runners; - if (currentRunners != null) { - for (int i = 0; i < currentRunners.length; i++) { + if( currentRunners != null ) + { + for( int i = 0; i < currentRunners.length; i++ ) + { TaskRunner runner = currentRunners[i]; // If we've no runner, skip. - if (runner == null || runner.owner == null || !runner.owner.isAlive()) { - if (!running) { + if( runner == null || runner.owner == null || !runner.owner.isAlive() ) + { + if( !running ) + { continue; } // Mark the old runner as dead and start a new one. - ComputerCraft.log.warn("Previous runner ({}) has crashed, restarting!", - runner != null && runner.owner != null ? runner.owner.getName() : runner); - if (runner != null) { + ComputerCraft.log.warn( "Previous runner ({}) has crashed, restarting!", + runner != null && runner.owner != null ? runner.owner.getName() : runner ); + if( runner != null ) + { runner.running = false; } - runnerFactory.newThread(runners[i] = new TaskRunner()) - .start(); + runnerFactory.newThread( runners[i] = new TaskRunner() ) + .start(); } // If the runner has no work, skip ComputerExecutor executor = runner.currentExecutor.get(); - if (executor == null) { + if( executor == null ) + { continue; } @@ -395,7 +451,8 @@ public final class ComputerThread { // then we can let the Lua machine do its work. long afterStart = executor.timeout.nanoCumulative(); long afterHardAbort = afterStart - TIMEOUT - ABORT_TIMEOUT; - if (afterHardAbort < 0) { + if( afterHardAbort < 0 ) + { continue; } @@ -403,34 +460,42 @@ public final class ComputerThread { executor.timeout.hardAbort(); executor.abort(); - if (afterHardAbort >= ABORT_TIMEOUT * 2) { + if( afterHardAbort >= ABORT_TIMEOUT * 2 ) + { // If we've hard aborted and interrupted, and we're still not dead, then mark the runner // as dead, finish off the task, and spawn a new runner. - timeoutTask(executor, runner.owner, afterStart); + timeoutTask( executor, runner.owner, afterStart ); runner.running = false; runner.owner.interrupt(); - ComputerExecutor thisExecutor = runner.currentExecutor.getAndSet(null); - if (thisExecutor != null) { - afterWork(runner, executor); + ComputerExecutor thisExecutor = runner.currentExecutor.getAndSet( null ); + if( thisExecutor != null ) + { + afterWork( runner, executor ); } - synchronized (threadLock) { - if (running && runners.length > i && runners[i] == runner) { - runnerFactory.newThread(currentRunners[i] = new TaskRunner()) - .start(); + synchronized( threadLock ) + { + if( running && runners.length > i && runners[i] == runner ) + { + runnerFactory.newThread( currentRunners[i] = new TaskRunner() ) + .start(); } } - } else if (afterHardAbort >= ABORT_TIMEOUT) { + } + else if( afterHardAbort >= ABORT_TIMEOUT ) + { // If we've hard aborted but we're still not dead, dump the stack trace and interrupt // the task. - timeoutTask(executor, runner.owner, afterStart); + timeoutTask( executor, runner.owner, afterStart ); runner.owner.interrupt(); } } } } - } catch (InterruptedException ignored) { + } + catch( InterruptedException ignored ) + { } } } @@ -441,31 +506,41 @@ public final class ComputerThread { * This is responsible for running the {@link ComputerExecutor#work()}, {@link ComputerExecutor#beforeWork()} and {@link ComputerExecutor#afterWork()} * functions. Everything else is either handled by the executor, timeout state or monitor. */ - private static final class TaskRunner implements Runnable { + private static final class TaskRunner implements Runnable + { final AtomicReference currentExecutor = new AtomicReference<>(); Thread owner; volatile boolean running = true; @Override - public void run() { + public void run() + { this.owner = Thread.currentThread(); tasks: - while (this.running && ComputerThread.running) { + while( this.running && ComputerThread.running ) + { // Wait for an active queue to execute ComputerExecutor executor; - try { + try + { computerLock.lockInterruptibly(); - try { - while (computerQueue.isEmpty()) { + try + { + while( computerQueue.isEmpty() ) + { hasWork.await(); } executor = computerQueue.pollFirst(); assert executor != null : "hasWork should ensure we never receive null work"; - } finally { + } + finally + { computerLock.unlock(); } - } catch (InterruptedException ignored) { + } + catch( InterruptedException ignored ) + { // If we've been interrupted, our running flag has probably been reset, so we'll // just jump into the next iteration. continue; @@ -473,14 +548,16 @@ public final class ComputerThread { // If we're trying to executing some task on this computer while someone else is doing work, something // is seriously wrong. - while (!executor.executingThread.compareAndSet(null, this.owner)) { + while( !executor.executingThread.compareAndSet( null, this.owner ) ) + { Thread existing = executor.executingThread.get(); - if (existing != null) { + if( existing != null ) + { ComputerCraft.log.error( "Trying to run computer #{} on thread {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.", executor.getComputer() - .getID(), this.owner.getName(), - existing.getName()); + .getID(), this.owner.getName(), + existing.getName() ); continue tasks; } } @@ -490,18 +567,24 @@ public final class ComputerThread { // And then set the current executor. It's important to do it afterwards, as otherwise we introduce // race conditions with the monitor. - this.currentExecutor.set(executor); + this.currentExecutor.set( executor ); // Execute the task - try { + try + { executor.work(); - } catch (Exception | LinkageError | VirtualMachineError e) { - ComputerCraft.log.error("Error running task on computer #" + executor.getComputer() - .getID(), e); - } finally { - ComputerExecutor thisExecutor = this.currentExecutor.getAndSet(null); - if (thisExecutor != null) { - afterWork(this, executor); + } + catch( Exception | LinkageError | VirtualMachineError e ) + { + ComputerCraft.log.error( "Error running task on computer #" + executor.getComputer() + .getID(), e ); + } + finally + { + ComputerExecutor thisExecutor = this.currentExecutor.getAndSet( null ); + if( thisExecutor != null ) + { + afterWork( this, executor ); } } } diff --git a/src/main/java/dan200/computercraft/core/computer/Environment.java b/src/main/java/dan200/computercraft/core/computer/Environment.java index 454333717..31b21539c 100644 --- a/src/main/java/dan200/computercraft/core/computer/Environment.java +++ b/src/main/java/dan200/computercraft/core/computer/Environment.java @@ -6,11 +6,6 @@ package dan200.computercraft.core.computer; -import java.util.Arrays; -import java.util.Iterator; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.ILuaAPI; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IWorkMonitor; @@ -22,6 +17,10 @@ import dan200.computercraft.core.tracking.TrackingField; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.Iterator; + /** * Represents the "environment" that a {@link Computer} exists in. * @@ -41,7 +40,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; *

    Peripheral

    * We also keep track of peripherals. These are read on both threads, and only written on the main thread. */ -public final class Environment implements IAPIEnvironment { +public final class Environment implements IAPIEnvironment +{ private final Computer computer; private final int[] internalOutput = new int[ComputerSide.COUNT]; private final int[] internalBundledOutput = new int[ComputerSide.COUNT]; @@ -56,58 +56,70 @@ public final class Environment implements IAPIEnvironment { private IPeripheralChangeListener peripheralListener = null; private int nextTimerToken = 0; - Environment(Computer computer) { + Environment( Computer computer ) + { this.computer = computer; } @Override - public int getComputerID() { + public int getComputerID() + { return this.computer.assignID(); } @Nonnull @Override - public IComputerEnvironment getComputerEnvironment() { + public IComputerEnvironment getComputerEnvironment() + { return this.computer.getComputerEnvironment(); } @Nonnull @Override - public IWorkMonitor getMainThreadMonitor() { + public IWorkMonitor getMainThreadMonitor() + { return this.computer.getMainThreadMonitor(); } @Nonnull @Override - public Terminal getTerminal() { + public Terminal getTerminal() + { return this.computer.getTerminal(); } @Override - public FileSystem getFileSystem() { + public FileSystem getFileSystem() + { return this.computer.getFileSystem(); } @Override - public void shutdown() { + public void shutdown() + { this.computer.shutdown(); } @Override - public void reboot() { + public void reboot() + { this.computer.reboot(); } @Override - public void queueEvent(String event, Object... args) { - this.computer.queueEvent(event, args); + public void queueEvent( String event, Object... args ) + { + this.computer.queueEvent( event, args ); } @Override - public void setOutput(ComputerSide side, int output) { + public void setOutput( ComputerSide side, int output ) + { int index = side.ordinal(); - synchronized (this.internalOutput) { - if (this.internalOutput[index] != output) { + synchronized( this.internalOutput ) + { + if( this.internalOutput[index] != output ) + { this.internalOutput[index] = output; this.internalOutputChanged = true; } @@ -115,22 +127,28 @@ public final class Environment implements IAPIEnvironment { } @Override - public int getOutput(ComputerSide side) { - synchronized (this.internalOutput) { + public int getOutput( ComputerSide side ) + { + synchronized( this.internalOutput ) + { return this.computer.isOn() ? this.internalOutput[side.ordinal()] : 0; } } @Override - public int getInput(ComputerSide side) { + public int getInput( ComputerSide side ) + { return this.input[side.ordinal()]; } @Override - public void setBundledOutput(ComputerSide side, int output) { + public void setBundledOutput( ComputerSide side, int output ) + { int index = side.ordinal(); - synchronized (this.internalOutput) { - if (this.internalBundledOutput[index] != output) { + synchronized( this.internalOutput ) + { + if( this.internalBundledOutput[index] != output ) + { this.internalBundledOutput[index] = output; this.internalOutputChanged = true; } @@ -138,80 +156,100 @@ public final class Environment implements IAPIEnvironment { } @Override - public int getBundledOutput(ComputerSide side) { - synchronized (this.internalOutput) { + public int getBundledOutput( ComputerSide side ) + { + synchronized( this.internalOutput ) + { return this.computer.isOn() ? this.internalBundledOutput[side.ordinal()] : 0; } } @Override - public int getBundledInput(ComputerSide side) { + public int getBundledInput( ComputerSide side ) + { return this.bundledInput[side.ordinal()]; } @Override - public void setPeripheralChangeListener(IPeripheralChangeListener listener) { - synchronized (this.peripherals) { + public void setPeripheralChangeListener( IPeripheralChangeListener listener ) + { + synchronized( this.peripherals ) + { this.peripheralListener = listener; } } @Override - public IPeripheral getPeripheral(ComputerSide side) { - synchronized (this.peripherals) { + public IPeripheral getPeripheral( ComputerSide side ) + { + synchronized( this.peripherals ) + { return this.peripherals[side.ordinal()]; } } @Override - public String getLabel() { + public String getLabel() + { return this.computer.getLabel(); } @Override - public void setLabel(String label) { - this.computer.setLabel(label); + public void setLabel( String label ) + { + this.computer.setLabel( label ); } @Override - public int startTimer(long ticks) { - synchronized (this.timers) { - this.timers.put(this.nextTimerToken, new Timer(ticks)); + public int startTimer( long ticks ) + { + synchronized( this.timers ) + { + this.timers.put( this.nextTimerToken, new Timer( ticks ) ); return this.nextTimerToken++; } } @Override - public void cancelTimer(int id) { - synchronized (this.timers) { - this.timers.remove(id); + public void cancelTimer( int id ) + { + synchronized( this.timers ) + { + this.timers.remove( id ); } } @Override - public void addTrackingChange(@Nonnull TrackingField field, long change) { - Tracking.addValue(this.computer, field, change); + public void addTrackingChange( @Nonnull TrackingField field, long change ) + { + Tracking.addValue( this.computer, field, change ); } - public int getExternalRedstoneOutput(ComputerSide side) { + public int getExternalRedstoneOutput( ComputerSide side ) + { return this.computer.isOn() ? this.externalOutput[side.ordinal()] : 0; } - public int getExternalBundledRedstoneOutput(ComputerSide side) { + public int getExternalBundledRedstoneOutput( ComputerSide side ) + { return this.computer.isOn() ? this.externalBundledOutput[side.ordinal()] : 0; } - public void setRedstoneInput(ComputerSide side, int level) { + public void setRedstoneInput( ComputerSide side, int level ) + { int index = side.ordinal(); - if (this.input[index] != level) { + if( this.input[index] != level ) + { this.input[index] = level; this.inputChanged = true; } } - public void setBundledRedstoneInput(ComputerSide side, int combination) { + public void setBundledRedstoneInput( ComputerSide side, int combination ) + { int index = side.ordinal(); - if (this.bundledInput[index] != combination) { + if( this.bundledInput[index] != combination ) + { this.bundledInput[index] = combination; this.inputChanged = true; } @@ -223,8 +261,10 @@ public final class Environment implements IAPIEnvironment { * @see ILuaAPI#startup() * @see ILuaAPI#shutdown() */ - void reset() { - synchronized (this.timers) { + void reset() + { + synchronized( this.timers ) + { this.timers.clear(); } } @@ -232,23 +272,28 @@ public final class Environment implements IAPIEnvironment { /** * Called on the main thread to update the internal state of the computer. */ - void tick() { - if (this.inputChanged) { + void tick() + { + if( this.inputChanged ) + { this.inputChanged = false; - this.queueEvent("redstone"); + this.queueEvent( "redstone" ); } - synchronized (this.timers) { + synchronized( this.timers ) + { // Countdown all of our active timers Iterator> it = this.timers.int2ObjectEntrySet() - .iterator(); - while (it.hasNext()) { + .iterator(); + while( it.hasNext() ) + { Int2ObjectMap.Entry entry = it.next(); Timer timer = entry.getValue(); timer.ticksLeft--; - if (timer.ticksLeft <= 0) { + if( timer.ticksLeft <= 0 ) + { // Queue the "timer" event - this.queueEvent(TIMER_EVENT, entry.getIntKey()); + this.queueEvent( TIMER_EVENT, entry.getIntKey() ); it.remove(); } } @@ -260,22 +305,28 @@ public final class Environment implements IAPIEnvironment { * * @return If the outputs have changed. */ - boolean updateOutput() { + boolean updateOutput() + { // Mark output as changed if the internal redstone has changed - synchronized (this.internalOutput) { - if (!this.internalOutputChanged) { + synchronized( this.internalOutput ) + { + if( !this.internalOutputChanged ) + { return false; } boolean changed = false; - for (int i = 0; i < ComputerSide.COUNT; i++) { - if (this.externalOutput[i] != this.internalOutput[i]) { + for( int i = 0; i < ComputerSide.COUNT; i++ ) + { + if( this.externalOutput[i] != this.internalOutput[i] ) + { this.externalOutput[i] = this.internalOutput[i]; changed = true; } - if (this.externalBundledOutput[i] != this.internalBundledOutput[i]) { + if( this.externalBundledOutput[i] != this.internalBundledOutput[i] ) + { this.externalBundledOutput[i] = this.internalBundledOutput[i]; changed = true; } @@ -287,32 +338,40 @@ public final class Environment implements IAPIEnvironment { } } - void resetOutput() { + void resetOutput() + { // Reset redstone output - synchronized (this.internalOutput) { - Arrays.fill(this.internalOutput, 0); - Arrays.fill(this.internalBundledOutput, 0); + synchronized( this.internalOutput ) + { + Arrays.fill( this.internalOutput, 0 ); + Arrays.fill( this.internalBundledOutput, 0 ); this.internalOutputChanged = true; } } - public void setPeripheral(ComputerSide side, IPeripheral peripheral) { - synchronized (this.peripherals) { + public void setPeripheral( ComputerSide side, IPeripheral peripheral ) + { + synchronized( this.peripherals ) + { int index = side.ordinal(); IPeripheral existing = this.peripherals[index]; - if ((existing == null && peripheral != null) || (existing != null && peripheral == null) || (existing != null && !existing.equals(peripheral))) { + if( (existing == null && peripheral != null) || (existing != null && peripheral == null) || (existing != null && !existing.equals( peripheral )) ) + { this.peripherals[index] = peripheral; - if (this.peripheralListener != null) { - this.peripheralListener.onPeripheralChanged(side, peripheral); + if( this.peripheralListener != null ) + { + this.peripheralListener.onPeripheralChanged( side, peripheral ); } } } } - private static class Timer { + private static class Timer + { long ticksLeft; - Timer(long ticksLeft) { + Timer( long ticksLeft ) + { this.ticksLeft = ticksLeft; } } diff --git a/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java b/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java index de87cf8dd..66487c42b 100644 --- a/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java +++ b/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java @@ -6,15 +6,15 @@ package dan200.computercraft.core.computer; -import java.io.InputStream; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; -public interface IComputerEnvironment { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.InputStream; + +public interface IComputerEnvironment +{ int getDay(); double getTimeOfDay(); @@ -32,11 +32,11 @@ public interface IComputerEnvironment { int assignNewID(); @Nullable - IWritableMount createSaveDirMount(String subPath, long capacity); + IWritableMount createSaveDirMount( String subPath, long capacity ); @Nullable - IMount createResourceMount(String domain, String subPath); + IMount createResourceMount( String domain, String subPath ); @Nullable - InputStream createResourceFile(String domain, String subPath); + InputStream createResourceFile( String domain, String subPath ); } diff --git a/src/main/java/dan200/computercraft/core/computer/MainThread.java b/src/main/java/dan200/computercraft/core/computer/MainThread.java index 1072b5c24..0187ff2db 100644 --- a/src/main/java/dan200/computercraft/core/computer/MainThread.java +++ b/src/main/java/dan200/computercraft/core/computer/MainThread.java @@ -6,15 +6,14 @@ package dan200.computercraft.core.computer; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.lua.ILuaTask; + +import javax.annotation.Nonnull; import java.util.HashSet; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; -import javax.annotation.Nonnull; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.ILuaTask; - /** * Runs tasks on the main (server) thread, ticks {@link MainThreadExecutor}s, and limits how much time is used this tick. * @@ -27,7 +26,8 @@ import dan200.computercraft.api.lua.ILuaTask; * Next tick, we put {@link ComputerCraft#maxMainGlobalTime} into our budget (and clamp it to that value to). If we're still over budget, then we should not * execute any work (either as part of {@link MainThread} or externally). */ -public final class MainThread { +public final class MainThread +{ /** * An internal counter for {@link ILuaTask} ids. * @@ -39,17 +39,19 @@ public final class MainThread { /** * The queue of {@link MainThreadExecutor}s with tasks to perform. */ - private static final TreeSet executors = new TreeSet<>((a, b) -> { - if (a == b) { + private static final TreeSet executors = new TreeSet<>( ( a, b ) -> { + if( a == b ) + { return 0; // Should never happen, but let's be consistent here } long at = a.virtualTime, bt = b.virtualTime; - if (at == bt) { - return Integer.compare(a.hashCode(), b.hashCode()); + if( at == bt ) + { + return Integer.compare( a.hashCode(), b.hashCode() ); } return at < bt ? -1 : 1; - }); + } ); /** * The set of executors which went over budget in a previous tick, and are waiting for their time to run down. @@ -82,14 +84,18 @@ public final class MainThread { private MainThread() {} - public static long getUniqueTaskID() { + public static long getUniqueTaskID() + { return lastTaskId.incrementAndGet(); } - static void queue(@Nonnull MainThreadExecutor executor, boolean sleeper) { - synchronized (executors) { - if (executor.onQueue) { - throw new IllegalStateException("Cannot queue already queued executor"); + static void queue( @Nonnull MainThreadExecutor executor, boolean sleeper ) + { + synchronized( executors ) + { + if( executor.onQueue ) + { + throw new IllegalStateException( "Cannot queue already queued executor" ); } executor.onQueue = true; executor.updateTime(); @@ -99,54 +105,63 @@ public final class MainThread { long newRuntime = minimumTime; // Slow down new computers a little bit. - if (executor.virtualTime == 0) { + if( executor.virtualTime == 0 ) + { newRuntime += ComputerCraft.maxMainComputerTime; } - executor.virtualTime = Math.max(newRuntime, executor.virtualTime); + executor.virtualTime = Math.max( newRuntime, executor.virtualTime ); - executors.add(executor); + executors.add( executor ); } } - static void cooling(@Nonnull MainThreadExecutor executor) { - cooling.add(executor); + static void cooling( @Nonnull MainThreadExecutor executor ) + { + cooling.add( executor ); } - static boolean canExecute() { + static boolean canExecute() + { return canExecute; } - static int currentTick() { + static int currentTick() + { return currentTick; } - public static void executePendingTasks() { + public static void executePendingTasks() + { // Move onto the next tick and cool down the global executor. We're allowed to execute if we have _any_ time // allocated for this tick. This means we'll stick much closer to doing MAX_TICK_TIME work every tick. // // Of course, we'll go over the MAX_TICK_TIME most of the time, but eventually that overrun will accumulate // and we'll skip a whole tick - bringing the average back down again. currentTick++; - budget = Math.min(budget + ComputerCraft.maxMainGlobalTime, ComputerCraft.maxMainGlobalTime); + budget = Math.min( budget + ComputerCraft.maxMainGlobalTime, ComputerCraft.maxMainGlobalTime ); canExecute = budget > 0; // Cool down any warm computers. - cooling.removeIf(MainThreadExecutor::tickCooling); + cooling.removeIf( MainThreadExecutor::tickCooling ); - if (!canExecute) { + if( !canExecute ) + { return; } // Run until we meet the deadline. long start = System.nanoTime(); long deadline = start + budget; - while (true) { + while( true ) + { MainThreadExecutor executor; - synchronized (executors) { + synchronized( executors ) + { executor = executors.pollFirst(); } - if (executor == null) { + if( executor == null ) + { break; } @@ -154,43 +169,51 @@ public final class MainThread { executor.execute(); long taskStop = System.nanoTime(); - synchronized (executors) { - if (executor.afterExecute(taskStop - taskStart)) { - executors.add(executor); + synchronized( executors ) + { + if( executor.afterExecute( taskStop - taskStart ) ) + { + executors.add( executor ); } // Compute the new minimum time (including the next task on the queue too). Note that this may also include // time spent in external tasks. long newMinimum = executor.virtualTime; - if (!executors.isEmpty()) { + if( !executors.isEmpty() ) + { MainThreadExecutor next = executors.first(); - if (next.virtualTime < newMinimum) { + if( next.virtualTime < newMinimum ) + { newMinimum = next.virtualTime; } } - minimumTime = Math.max(minimumTime, newMinimum); + minimumTime = Math.max( minimumTime, newMinimum ); } - if (taskStop >= deadline) { + if( taskStop >= deadline ) + { break; } } - consumeTime(System.nanoTime() - start); + consumeTime( System.nanoTime() - start ); } - static void consumeTime(long time) { + static void consumeTime( long time ) + { budget -= time; } - public static void reset() { + public static void reset() + { currentTick = 0; budget = 0; canExecute = true; minimumTime = 0; - lastTaskId.set(0); + lastTaskId.set( 0 ); cooling.clear(); - synchronized (executors) { + synchronized( executors ) + { executors.clear(); } } diff --git a/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java b/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java index 5f9538dfd..74be06df7 100644 --- a/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java +++ b/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java @@ -6,17 +6,16 @@ package dan200.computercraft.core.computer; -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.TimeUnit; - -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IWorkMonitor; import dan200.computercraft.core.tracking.Tracking; import dan200.computercraft.shared.turtle.core.TurtleBrain; +import javax.annotation.Nonnull; +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.concurrent.TimeUnit; + /** * Keeps track of tasks that a {@link Computer} should run on the main thread and how long that has been spent executing them. * @@ -46,7 +45,8 @@ import dan200.computercraft.shared.turtle.core.TurtleBrain; * @see Computer#getMainThreadMonitor() * @see Computer#queueMainThread(Runnable) */ -final class MainThreadExecutor implements IWorkMonitor { +final class MainThreadExecutor implements IWorkMonitor +{ /** * The maximum number of {@link MainThread} tasks allowed on the queue. */ @@ -65,7 +65,7 @@ final class MainThreadExecutor implements IWorkMonitor { * * @see #queueLock */ - private final Queue tasks = new ArrayDeque<>(4); + private final Queue tasks = new ArrayDeque<>( 4 ); /** * Determines if this executor is currently present on the queue. @@ -100,7 +100,8 @@ final class MainThreadExecutor implements IWorkMonitor { private State state = State.COOL; private long pendingTime; - MainThreadExecutor(Computer computer) { + MainThreadExecutor( Computer computer ) + { this.computer = computer; } @@ -110,29 +111,37 @@ final class MainThreadExecutor implements IWorkMonitor { * @param runnable The task to run on the main thread. * @return Whether this task was enqueued (namely, was there space). */ - boolean enqueue(Runnable runnable) { - synchronized (this.queueLock) { - if (this.tasks.size() >= MAX_TASKS || !this.tasks.offer(runnable)) { + boolean enqueue( Runnable runnable ) + { + synchronized( this.queueLock ) + { + if( this.tasks.size() >= MAX_TASKS || !this.tasks.offer( runnable ) ) + { return false; } - if (!this.onQueue && this.state == State.COOL) { - MainThread.queue(this, true); + if( !this.onQueue && this.state == State.COOL ) + { + MainThread.queue( this, true ); } return true; } } - void execute() { - if (this.state != State.COOL) { + void execute() + { + if( this.state != State.COOL ) + { return; } Runnable task; - synchronized (this.queueLock) { + synchronized( this.queueLock ) + { task = this.tasks.poll(); } - if (task != null) { + if( task != null ) + { task.run(); } } @@ -143,25 +152,30 @@ final class MainThreadExecutor implements IWorkMonitor { * @param time The time some task took to run. * @return Whether this should be added back to the queue. */ - boolean afterExecute(long time) { - this.consumeTime(time); + boolean afterExecute( long time ) + { + this.consumeTime( time ); - synchronized (this.queueLock) { + synchronized( this.queueLock ) + { this.virtualTime += time; this.updateTime(); - if (this.state != State.COOL || this.tasks.isEmpty()) { + if( this.state != State.COOL || this.tasks.isEmpty() ) + { return this.onQueue = false; } return true; } } - private void consumeTime(long time) { - Tracking.addServerTiming(this.computer, time); + private void consumeTime( long time ) + { + Tracking.addServerTiming( this.computer, time ); // Reset the budget if moving onto a new tick. We know this is safe, as this will only have happened if // #tickCooling() isn't called, and so we didn't overrun the previous tick. - if (this.currentTick != MainThread.currentTick()) { + if( this.currentTick != MainThread.currentTick() ) + { this.currentTick = MainThread.currentTick(); this.budget = ComputerCraft.maxMainComputerTime; } @@ -169,19 +183,22 @@ final class MainThreadExecutor implements IWorkMonitor { this.budget -= time; // If we've gone over our limit, mark us as having to cool down. - if (this.budget < 0 && this.state == State.COOL) { + if( this.budget < 0 && this.state == State.COOL ) + { this.state = State.HOT; - MainThread.cooling(this); + MainThread.cooling( this ); } } - void updateTime() { + void updateTime() + { this.virtualTime += this.pendingTime; this.pendingTime = 0; } @Override - public boolean shouldWork() { + public boolean shouldWork() + { return this.state == State.COOL && MainThread.canExecute(); } @@ -191,19 +208,22 @@ final class MainThreadExecutor implements IWorkMonitor { * @return Whether we can execute external tasks. */ @Override - public boolean canWork() { + public boolean canWork() + { return this.state != State.COOLING && MainThread.canExecute(); } @Override - public void trackWork(long time, @Nonnull TimeUnit unit) { - long nanoTime = unit.toNanos(time); - synchronized (this.queueLock) { + public void trackWork( long time, @Nonnull TimeUnit unit ) + { + long nanoTime = unit.toNanos( time ); + synchronized( this.queueLock ) + { this.pendingTime += nanoTime; } - this.consumeTime(nanoTime); - MainThread.consumeTime(nanoTime); + this.consumeTime( nanoTime ); + MainThread.consumeTime( nanoTime ); } /** @@ -211,24 +231,29 @@ final class MainThreadExecutor implements IWorkMonitor { * * @return Whether this executor has cooled down, and so is safe to run again. */ - boolean tickCooling() { + boolean tickCooling() + { this.state = State.COOLING; this.currentTick = MainThread.currentTick(); - this.budget = Math.min(this.budget + ComputerCraft.maxMainComputerTime, ComputerCraft.maxMainComputerTime); - if (this.budget < ComputerCraft.maxMainComputerTime) { + this.budget = Math.min( this.budget + ComputerCraft.maxMainComputerTime, ComputerCraft.maxMainComputerTime ); + if( this.budget < ComputerCraft.maxMainComputerTime ) + { return false; } this.state = State.COOL; - synchronized (this.queueLock) { - if (!this.tasks.isEmpty() && !this.onQueue) { - MainThread.queue(this, false); + synchronized( this.queueLock ) + { + if( !this.tasks.isEmpty() && !this.onQueue ) + { + MainThread.queue( this, false ); } } return true; } - private enum State { + private enum State + { COOL, HOT, COOLING, } } diff --git a/src/main/java/dan200/computercraft/core/computer/TimeoutState.java b/src/main/java/dan200/computercraft/core/computer/TimeoutState.java index 02d6bf064..550bc59fc 100644 --- a/src/main/java/dan200/computercraft/core/computer/TimeoutState.java +++ b/src/main/java/dan200/computercraft/core/computer/TimeoutState.java @@ -6,11 +6,11 @@ package dan200.computercraft.core.computer; -import java.util.concurrent.TimeUnit; - import dan200.computercraft.core.lua.ILuaMachine; import dan200.computercraft.core.lua.MachineResult; +import java.util.concurrent.TimeUnit; + /** * Used to measure how long a computer has executed for, and thus the relevant timeout states. * @@ -31,7 +31,8 @@ import dan200.computercraft.core.lua.MachineResult; * @see ILuaMachine * @see MachineResult#isPause() */ -public final class TimeoutState { +public final class TimeoutState +{ /** * The error message to display when we trigger an abort. */ @@ -39,11 +40,11 @@ public final class TimeoutState { /** * The total time a task is allowed to run before aborting in nanoseconds. */ - static final long TIMEOUT = TimeUnit.MILLISECONDS.toNanos(7000); + static final long TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 7000 ); /** * The time the task is allowed to run after each abort in nanoseconds. */ - static final long ABORT_TIMEOUT = TimeUnit.MILLISECONDS.toNanos(1500); + static final long ABORT_TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 1500 ); private boolean paused; private boolean softAbort; private volatile boolean hardAbort; @@ -68,25 +69,30 @@ public final class TimeoutState { */ private long currentDeadline; - long nanoCumulative() { + long nanoCumulative() + { return System.nanoTime() - this.cumulativeStart; } - long nanoCurrent() { + long nanoCurrent() + { return System.nanoTime() - this.currentStart; } /** * Recompute the {@link #isSoftAborted()} and {@link #isPaused()} flags. */ - public void refresh() { + public void refresh() + { // Important: The weird arithmetic here is important, as nanoTime may return negative values, and so we // need to handle overflow. long now = System.nanoTime(); - if (!this.paused) { + if( !this.paused ) + { this.paused = this.currentDeadline - now <= 0 && ComputerThread.hasPendingWork(); // now >= currentDeadline } - if (!this.softAbort) { + if( !this.softAbort ) + { this.softAbort = now - this.cumulativeStart - TIMEOUT >= 0; // now - cumulativeStart >= TIMEOUT } } @@ -98,7 +104,8 @@ public final class TimeoutState { * * @return Whether we should pause execution. */ - public boolean isPaused() { + public boolean isPaused() + { return this.paused; } @@ -107,7 +114,8 @@ public final class TimeoutState { * * @return {@code true} if we should throw a timeout error. */ - public boolean isSoftAborted() { + public boolean isSoftAborted() + { return this.softAbort; } @@ -116,21 +124,24 @@ public final class TimeoutState { * * @return {@code true} if the machine should be forcibly shut down. */ - public boolean isHardAborted() { + public boolean isHardAborted() + { return this.hardAbort; } /** * If the machine should be forcibly aborted. */ - void hardAbort() { + void hardAbort() + { this.softAbort = this.hardAbort = true; } /** * Start the current and cumulative timers again. */ - void startTimer() { + void startTimer() + { long now = System.nanoTime(); this.currentStart = now; this.currentDeadline = now + ComputerThread.scaledPeriod(); @@ -143,7 +154,8 @@ public final class TimeoutState { * * @see #nanoCumulative() */ - void pauseTimer() { + void pauseTimer() + { // We set the cumulative time to difference between current time and "nominal start time". this.cumulativeElapsed = System.nanoTime() - this.cumulativeStart; this.paused = false; @@ -152,7 +164,8 @@ public final class TimeoutState { /** * Resets the cumulative time and resets the abort flags. */ - void stopTimer() { + void stopTimer() + { this.cumulativeElapsed = 0; this.paused = this.softAbort = this.hardAbort = false; } diff --git a/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java b/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java index 43f4472e1..65f4c1250 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java @@ -6,6 +6,10 @@ package dan200.computercraft.core.filesystem; +import dan200.computercraft.api.filesystem.FileOperationException; +import dan200.computercraft.api.filesystem.IMount; + +import javax.annotation.Nonnull; import java.io.IOException; import java.nio.channels.ReadableByteChannel; import java.nio.file.attribute.BasicFileAttributes; @@ -14,81 +18,98 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import javax.annotation.Nonnull; - -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; - -public class ComboMount implements IMount { +public class ComboMount implements IMount +{ private IMount[] m_parts; - public ComboMount(IMount[] parts) { + public ComboMount( IMount[] parts ) + { this.m_parts = parts; } // IMount implementation @Override - public void list(@Nonnull String path, @Nonnull List contents) throws IOException { + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { // Combine the lists from all the mounts List foundFiles = null; int foundDirs = 0; - for (int i = this.m_parts.length - 1; i >= 0; --i) { + for( int i = this.m_parts.length - 1; i >= 0; --i ) + { IMount part = this.m_parts[i]; - if (part.exists(path) && part.isDirectory(path)) { - if (foundFiles == null) { + if( part.exists( path ) && part.isDirectory( path ) ) + { + if( foundFiles == null ) + { foundFiles = new ArrayList<>(); } - part.list(path, foundFiles); + part.list( path, foundFiles ); foundDirs++; } } - if (foundDirs == 1) { + if( foundDirs == 1 ) + { // We found one directory, so we know it already doesn't contain duplicates - contents.addAll(foundFiles); - } else if (foundDirs > 1) { + contents.addAll( foundFiles ); + } + else if( foundDirs > 1 ) + { // We found multiple directories, so filter for duplicates Set seen = new HashSet<>(); - for (String file : foundFiles) { - if (seen.add(file)) { - contents.add(file); + for( String file : foundFiles ) + { + if( seen.add( file ) ) + { + contents.add( file ); } } - } else { - throw new FileOperationException(path, "Not a directory"); + } + else + { + throw new FileOperationException( path, "Not a directory" ); } } @Nonnull @Override - public ReadableByteChannel openForRead(@Nonnull String path) throws IOException { - for (int i = this.m_parts.length - 1; i >= 0; --i) { + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + for( int i = this.m_parts.length - 1; i >= 0; --i ) + { IMount part = this.m_parts[i]; - if (part.exists(path) && !part.isDirectory(path)) { - return part.openForRead(path); + if( part.exists( path ) && !part.isDirectory( path ) ) + { + return part.openForRead( path ); } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } @Nonnull @Override - public BasicFileAttributes getAttributes(@Nonnull String path) throws IOException { - for (int i = this.m_parts.length - 1; i >= 0; --i) { + public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException + { + for( int i = this.m_parts.length - 1; i >= 0; --i ) + { IMount part = this.m_parts[i]; - if (part.exists(path) && !part.isDirectory(path)) { - return part.getAttributes(path); + if( part.exists( path ) && !part.isDirectory( path ) ) + { + return part.getAttributes( path ); } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } @Override - public boolean exists(@Nonnull String path) throws IOException { - for (int i = this.m_parts.length - 1; i >= 0; --i) { + public boolean exists( @Nonnull String path ) throws IOException + { + for( int i = this.m_parts.length - 1; i >= 0; --i ) + { IMount part = this.m_parts[i]; - if (part.exists(path)) { + if( part.exists( path ) ) + { return true; } } @@ -96,10 +117,13 @@ public class ComboMount implements IMount { } @Override - public boolean isDirectory(@Nonnull String path) throws IOException { - for (int i = this.m_parts.length - 1; i >= 0; --i) { + public boolean isDirectory( @Nonnull String path ) throws IOException + { + for( int i = this.m_parts.length - 1; i >= 0; --i ) + { IMount part = this.m_parts[i]; - if (part.isDirectory(path)) { + if( part.isDirectory( path ) ) + { return true; } } @@ -107,13 +131,16 @@ public class ComboMount implements IMount { } @Override - public long getSize(@Nonnull String path) throws IOException { - for (int i = this.m_parts.length - 1; i >= 0; --i) { + public long getSize( @Nonnull String path ) throws IOException + { + for( int i = this.m_parts.length - 1; i >= 0; --i ) + { IMount part = this.m_parts[i]; - if (part.exists(path)) { - return part.getSize(path); + if( part.exists( path ) ) + { + return part.getSize( path ); } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java b/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java index 5597fa1e1..2b3050fe5 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java @@ -6,38 +6,43 @@ package dan200.computercraft.core.filesystem; +import dan200.computercraft.api.filesystem.FileOperationException; +import dan200.computercraft.api.filesystem.IMount; + +import javax.annotation.Nonnull; import java.io.IOException; import java.nio.channels.ReadableByteChannel; import java.util.List; -import javax.annotation.Nonnull; - -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; - -public class EmptyMount implements IMount { +public class EmptyMount implements IMount +{ @Override - public void list(@Nonnull String path, @Nonnull List contents) { + public void list( @Nonnull String path, @Nonnull List contents ) + { } @Nonnull @Override - public ReadableByteChannel openForRead(@Nonnull String path) throws IOException { - throw new FileOperationException(path, "No such file"); + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + throw new FileOperationException( path, "No such file" ); } @Override - public boolean exists(@Nonnull String path) { + public boolean exists( @Nonnull String path ) + { return path.isEmpty(); } @Override - public boolean isDirectory(@Nonnull String path) { + public boolean isDirectory( @Nonnull String path ) + { return path.isEmpty(); } @Override - public long getSize(@Nonnull String path) { + public long getSize( @Nonnull String path ) + { return 0; } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileMount.java b/src/main/java/dan200/computercraft/core/filesystem/FileMount.java index 48049e05d..37627333d 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/FileMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/FileMount.java @@ -6,65 +6,63 @@ package dan200.computercraft.core.filesystem; +import com.google.common.collect.Sets; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.filesystem.FileOperationException; +import dan200.computercraft.api.filesystem.IWritableMount; + +import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.FileChannel; -import java.nio.channels.NonReadableChannelException; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.SeekableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardOpenOption; +import java.nio.channels.*; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; import java.util.List; import java.util.OptionalLong; import java.util.Set; -import javax.annotation.Nonnull; - -import com.google.common.collect.Sets; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IWritableMount; - -public class FileMount implements IWritableMount { +public class FileMount implements IWritableMount +{ private static final int MINIMUM_FILE_SIZE = 500; - private static final Set READ_OPTIONS = Collections.singleton(StandardOpenOption.READ); - private static final Set WRITE_OPTIONS = Sets.newHashSet(StandardOpenOption.WRITE, - StandardOpenOption.CREATE, - StandardOpenOption.TRUNCATE_EXISTING); - private static final Set APPEND_OPTIONS = Sets.newHashSet(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND); + private static final Set READ_OPTIONS = Collections.singleton( StandardOpenOption.READ ); + private static final Set WRITE_OPTIONS = Sets.newHashSet( StandardOpenOption.WRITE, + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING ); + private static final Set APPEND_OPTIONS = Sets.newHashSet( StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND ); private File m_rootPath; private long m_capacity; private long m_usedSpace; - public FileMount(File rootPath, long capacity) { + + public FileMount( File rootPath, long capacity ) + { this.m_rootPath = rootPath; this.m_capacity = capacity + MINIMUM_FILE_SIZE; - this.m_usedSpace = this.created() ? measureUsedSpace(this.m_rootPath) : MINIMUM_FILE_SIZE; + this.m_usedSpace = this.created() ? measureUsedSpace( this.m_rootPath ) : MINIMUM_FILE_SIZE; } - private boolean created() { + private boolean created() + { return this.m_rootPath.exists(); } - private static long measureUsedSpace(File file) { - if (!file.exists()) { + private static long measureUsedSpace( File file ) + { + if( !file.exists() ) + { return 0; } - try { + try + { Visitor visitor = new Visitor(); - Files.walkFileTree(file.toPath(), visitor); + Files.walkFileTree( file.toPath(), visitor ); return visitor.size; - } catch (IOException e) { - ComputerCraft.log.error("Error computing file size for {}", file, e); + } + catch( IOException e ) + { + ComputerCraft.log.error( "Error computing file size for {}", file, e ); return 0; } } @@ -72,326 +70,406 @@ public class FileMount implements IWritableMount { // IMount implementation @Override - public void list(@Nonnull String path, @Nonnull List contents) throws IOException { - if (!this.created()) { - if (!path.isEmpty()) { - throw new FileOperationException(path, "Not a directory"); + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + if( !this.created() ) + { + if( !path.isEmpty() ) + { + throw new FileOperationException( path, "Not a directory" ); } return; } - File file = this.getRealPath(path); - if (!file.exists() || !file.isDirectory()) { - throw new FileOperationException(path, "Not a directory"); + File file = this.getRealPath( path ); + if( !file.exists() || !file.isDirectory() ) + { + throw new FileOperationException( path, "Not a directory" ); } String[] paths = file.list(); - for (String subPath : paths) { - if (new File(file, subPath).exists()) { - contents.add(subPath); + for( String subPath : paths ) + { + if( new File( file, subPath ).exists() ) + { + contents.add( subPath ); } } } @Nonnull @Override - public ReadableByteChannel openForRead(@Nonnull String path) throws IOException { - if (this.created()) { - File file = this.getRealPath(path); - if (file.exists() && !file.isDirectory()) { - return FileChannel.open(file.toPath(), READ_OPTIONS); + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + if( this.created() ) + { + File file = this.getRealPath( path ); + if( file.exists() && !file.isDirectory() ) + { + return FileChannel.open( file.toPath(), READ_OPTIONS ); } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } @Nonnull @Override - public BasicFileAttributes getAttributes(@Nonnull String path) throws IOException { - if (this.created()) { - File file = this.getRealPath(path); - if (file.exists()) { - return Files.readAttributes(file.toPath(), BasicFileAttributes.class); + public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException + { + if( this.created() ) + { + File file = this.getRealPath( path ); + if( file.exists() ) + { + return Files.readAttributes( file.toPath(), BasicFileAttributes.class ); } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } @Override - public boolean exists(@Nonnull String path) { - if (!this.created()) { + public boolean exists( @Nonnull String path ) + { + if( !this.created() ) + { return path.isEmpty(); } - File file = this.getRealPath(path); + File file = this.getRealPath( path ); return file.exists(); } @Override - public boolean isDirectory(@Nonnull String path) { - if (!this.created()) { + public boolean isDirectory( @Nonnull String path ) + { + if( !this.created() ) + { return path.isEmpty(); } - File file = this.getRealPath(path); + File file = this.getRealPath( path ); return file.exists() && file.isDirectory(); } @Override - public long getSize(@Nonnull String path) throws IOException { - if (!this.created()) { - if (path.isEmpty()) { + public long getSize( @Nonnull String path ) throws IOException + { + if( !this.created() ) + { + if( path.isEmpty() ) + { return 0; } - } else { - File file = this.getRealPath(path); - if (file.exists()) { + } + else + { + File file = this.getRealPath( path ); + if( file.exists() ) + { return file.isDirectory() ? 0 : file.length(); } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } // IWritableMount implementation - private File getRealPath(String path) { - return new File(this.m_rootPath, path); + private File getRealPath( String path ) + { + return new File( this.m_rootPath, path ); } @Override - public void makeDirectory(@Nonnull String path) throws IOException { + public void makeDirectory( @Nonnull String path ) throws IOException + { this.create(); - File file = this.getRealPath(path); - if (file.exists()) { - if (!file.isDirectory()) { - throw new FileOperationException(path, "File exists"); + File file = this.getRealPath( path ); + if( file.exists() ) + { + if( !file.isDirectory() ) + { + throw new FileOperationException( path, "File exists" ); } return; } int dirsToCreate = 1; File parent = file.getParentFile(); - while (!parent.exists()) { + while( !parent.exists() ) + { ++dirsToCreate; parent = parent.getParentFile(); } - if (this.getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE) { - throw new FileOperationException(path, "Out of space"); + if( this.getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE ) + { + throw new FileOperationException( path, "Out of space" ); } - if (file.mkdirs()) { + if( file.mkdirs() ) + { this.m_usedSpace += dirsToCreate * MINIMUM_FILE_SIZE; - } else { - throw new FileOperationException(path, "Access denied"); + } + else + { + throw new FileOperationException( path, "Access denied" ); } } @Override - public void delete(@Nonnull String path) throws IOException { - if (path.isEmpty()) { - throw new FileOperationException(path, "Access denied"); + public void delete( @Nonnull String path ) throws IOException + { + if( path.isEmpty() ) + { + throw new FileOperationException( path, "Access denied" ); } - if (this.created()) { - File file = this.getRealPath(path); - if (file.exists()) { - this.deleteRecursively(file); + if( this.created() ) + { + File file = this.getRealPath( path ); + if( file.exists() ) + { + this.deleteRecursively( file ); } } } @Nonnull @Override - public WritableByteChannel openForWrite(@Nonnull String path) throws IOException { + public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException + { this.create(); - File file = this.getRealPath(path); - if (file.exists() && file.isDirectory()) { - throw new FileOperationException(path, "Cannot write to directory"); + File file = this.getRealPath( path ); + if( file.exists() && file.isDirectory() ) + { + throw new FileOperationException( path, "Cannot write to directory" ); } - if (file.exists()) { - this.m_usedSpace -= Math.max(file.length(), MINIMUM_FILE_SIZE); - } else if (this.getRemainingSpace() < MINIMUM_FILE_SIZE) { - throw new FileOperationException(path, "Out of space"); + if( file.exists() ) + { + this.m_usedSpace -= Math.max( file.length(), MINIMUM_FILE_SIZE ); + } + else if( this.getRemainingSpace() < MINIMUM_FILE_SIZE ) + { + throw new FileOperationException( path, "Out of space" ); } this.m_usedSpace += MINIMUM_FILE_SIZE; - return new SeekableCountingChannel(Files.newByteChannel(file.toPath(), WRITE_OPTIONS), MINIMUM_FILE_SIZE); + return new SeekableCountingChannel( Files.newByteChannel( file.toPath(), WRITE_OPTIONS ), MINIMUM_FILE_SIZE ); } @Nonnull @Override - public WritableByteChannel openForAppend(@Nonnull String path) throws IOException { - if (!this.created()) { - throw new FileOperationException(path, "No such file"); + public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException + { + if( !this.created() ) + { + throw new FileOperationException( path, "No such file" ); } - File file = this.getRealPath(path); - if (!file.exists()) { - throw new FileOperationException(path, "No such file"); + File file = this.getRealPath( path ); + if( !file.exists() ) + { + throw new FileOperationException( path, "No such file" ); } - if (file.isDirectory()) { - throw new FileOperationException(path, "Cannot write to directory"); + if( file.isDirectory() ) + { + throw new FileOperationException( path, "Cannot write to directory" ); } // Allowing seeking when appending is not recommended, so we use a separate channel. - return new WritableCountingChannel(Files.newByteChannel(file.toPath(), APPEND_OPTIONS), Math.max(MINIMUM_FILE_SIZE - file.length(), 0)); + return new WritableCountingChannel( Files.newByteChannel( file.toPath(), APPEND_OPTIONS ), Math.max( MINIMUM_FILE_SIZE - file.length(), 0 ) ); } @Override - public long getRemainingSpace() { - return Math.max(this.m_capacity - this.m_usedSpace, 0); + public long getRemainingSpace() + { + return Math.max( this.m_capacity - this.m_usedSpace, 0 ); } @Nonnull @Override - public OptionalLong getCapacity() { - return OptionalLong.of(this.m_capacity - MINIMUM_FILE_SIZE); + public OptionalLong getCapacity() + { + return OptionalLong.of( this.m_capacity - MINIMUM_FILE_SIZE ); } - private void create() throws IOException { - if (!this.m_rootPath.exists()) { + private void create() throws IOException + { + if( !this.m_rootPath.exists() ) + { boolean success = this.m_rootPath.mkdirs(); - if (!success) { - throw new IOException("Access denied"); + if( !success ) + { + throw new IOException( "Access denied" ); } } } - private void deleteRecursively(File file) throws IOException { + private void deleteRecursively( File file ) throws IOException + { // Empty directories first - if (file.isDirectory()) { + if( file.isDirectory() ) + { String[] children = file.list(); - for (String aChildren : children) { - this.deleteRecursively(new File(file, aChildren)); + for( String aChildren : children ) + { + this.deleteRecursively( new File( file, aChildren ) ); } } // Then delete long fileSize = file.isDirectory() ? 0 : file.length(); boolean success = file.delete(); - if (success) { - this.m_usedSpace -= Math.max(MINIMUM_FILE_SIZE, fileSize); - } else { - throw new IOException("Access denied"); + if( success ) + { + this.m_usedSpace -= Math.max( MINIMUM_FILE_SIZE, fileSize ); + } + else + { + throw new IOException( "Access denied" ); } } - private static class Visitor extends SimpleFileVisitor { + private static class Visitor extends SimpleFileVisitor + { long size; @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs ) + { this.size += MINIMUM_FILE_SIZE; return FileVisitResult.CONTINUE; } @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - this.size += Math.max(attrs.size(), MINIMUM_FILE_SIZE); + public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) + { + this.size += Math.max( attrs.size(), MINIMUM_FILE_SIZE ); return FileVisitResult.CONTINUE; } @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - ComputerCraft.log.error("Error computing file size for {}", file, exc); + public FileVisitResult visitFileFailed( Path file, IOException exc ) + { + ComputerCraft.log.error( "Error computing file size for {}", file, exc ); return FileVisitResult.CONTINUE; } } - private class WritableCountingChannel implements WritableByteChannel { + private class WritableCountingChannel implements WritableByteChannel + { private final WritableByteChannel m_inner; long m_ignoredBytesLeft; - WritableCountingChannel(WritableByteChannel inner, long bytesToIgnore) { + WritableCountingChannel( WritableByteChannel inner, long bytesToIgnore ) + { this.m_inner = inner; this.m_ignoredBytesLeft = bytesToIgnore; } @Override - public int write(@Nonnull ByteBuffer b) throws IOException { - this.count(b.remaining()); - return this.m_inner.write(b); + public int write( @Nonnull ByteBuffer b ) throws IOException + { + this.count( b.remaining() ); + return this.m_inner.write( b ); } - void count(long n) throws IOException { + void count( long n ) throws IOException + { this.m_ignoredBytesLeft -= n; - if (this.m_ignoredBytesLeft < 0) { + if( this.m_ignoredBytesLeft < 0 ) + { long newBytes = -this.m_ignoredBytesLeft; this.m_ignoredBytesLeft = 0; long bytesLeft = FileMount.this.m_capacity - FileMount.this.m_usedSpace; - if (newBytes > bytesLeft) { - throw new IOException("Out of space"); + if( newBytes > bytesLeft ) + { + throw new IOException( "Out of space" ); } FileMount.this.m_usedSpace += newBytes; } } @Override - public boolean isOpen() { + public boolean isOpen() + { return this.m_inner.isOpen(); } @Override - public void close() throws IOException { + public void close() throws IOException + { this.m_inner.close(); } } - private class SeekableCountingChannel extends WritableCountingChannel implements SeekableByteChannel { + private class SeekableCountingChannel extends WritableCountingChannel implements SeekableByteChannel + { private final SeekableByteChannel m_inner; - SeekableCountingChannel(SeekableByteChannel inner, long bytesToIgnore) { - super(inner, bytesToIgnore); + SeekableCountingChannel( SeekableByteChannel inner, long bytesToIgnore ) + { + super( inner, bytesToIgnore ); this.m_inner = inner; } @Override - public int read(ByteBuffer dst) throws ClosedChannelException { - if (!this.m_inner.isOpen()) { + public int read( ByteBuffer dst ) throws ClosedChannelException + { + if( !this.m_inner.isOpen() ) + { throw new ClosedChannelException(); } throw new NonReadableChannelException(); } @Override - public long position() throws IOException { + public long position() throws IOException + { return this.m_inner.position(); } @Override - public SeekableByteChannel position(long newPosition) throws IOException { - if (!this.isOpen()) { + public SeekableByteChannel position( long newPosition ) throws IOException + { + if( !this.isOpen() ) + { throw new ClosedChannelException(); } - if (newPosition < 0) { - throw new IllegalArgumentException("Cannot seek before the beginning of the stream"); + if( newPosition < 0 ) + { + throw new IllegalArgumentException( "Cannot seek before the beginning of the stream" ); } long delta = newPosition - this.m_inner.position(); - if (delta < 0) { + if( delta < 0 ) + { this.m_ignoredBytesLeft -= delta; - } else { - this.count(delta); + } + else + { + this.count( delta ); } - return this.m_inner.position(newPosition); + return this.m_inner.position( newPosition ); } @Override - public long size() throws IOException { + public long size() throws IOException + { return this.m_inner.size(); } @Override - public SeekableByteChannel truncate(long size) throws IOException { - throw new IOException("Not yet implemented"); + public SeekableByteChannel truncate( long size ) throws IOException + { + throw new IOException( "Not yet implemented" ); } } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java b/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java index f63e3e615..8756e0ea8 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java +++ b/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java @@ -6,10 +6,12 @@ package dan200.computercraft.core.filesystem; -public class FileSystemException extends Exception { +public class FileSystemException extends Exception +{ private static final long serialVersionUID = -2500631644868104029L; - FileSystemException(String s) { - super(s); + FileSystemException( String s ) + { + super( s ); } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java b/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java index 87e44fd8b..dfa3324af 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java @@ -6,6 +6,9 @@ package dan200.computercraft.core.filesystem; +import dan200.computercraft.api.filesystem.IFileSystem; + +import javax.annotation.Nonnull; import java.io.IOException; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; @@ -13,134 +16,181 @@ import java.util.Collections; import java.util.List; import java.util.function.Function; -import javax.annotation.Nonnull; - -import dan200.computercraft.api.filesystem.IFileSystem; - -public class FileSystemWrapperMount implements IFileSystem { +public class FileSystemWrapperMount implements IFileSystem +{ private final FileSystem m_filesystem; - public FileSystemWrapperMount(FileSystem filesystem) { + public FileSystemWrapperMount( FileSystem filesystem ) + { this.m_filesystem = filesystem; } @Override - public void makeDirectory(@Nonnull String path) throws IOException { - try { - this.m_filesystem.makeDir(path); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public void makeDirectory( @Nonnull String path ) throws IOException + { + try + { + this.m_filesystem.makeDir( path ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public void delete(@Nonnull String path) throws IOException { - try { - this.m_filesystem.delete(path); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public void delete( @Nonnull String path ) throws IOException + { + try + { + this.m_filesystem.delete( path ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Nonnull @Override - public WritableByteChannel openForWrite(@Nonnull String path) throws IOException { - try { - return this.m_filesystem.openForWrite(path, false, Function.identity()) - .get(); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException + { + try + { + return this.m_filesystem.openForWrite( path, false, Function.identity() ) + .get(); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Nonnull @Override - public WritableByteChannel openForAppend(@Nonnull String path) throws IOException { - try { - return this.m_filesystem.openForWrite(path, true, Function.identity()) - .get(); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException + { + try + { + return this.m_filesystem.openForWrite( path, true, Function.identity() ) + .get(); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public long getRemainingSpace() throws IOException { - try { - return this.m_filesystem.getFreeSpace("/"); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public long getRemainingSpace() throws IOException + { + try + { + return this.m_filesystem.getFreeSpace( "/" ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public void list(@Nonnull String path, @Nonnull List contents) throws IOException { - try { - Collections.addAll(contents, this.m_filesystem.list(path)); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + try + { + Collections.addAll( contents, this.m_filesystem.list( path ) ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Nonnull @Override - public ReadableByteChannel openForRead(@Nonnull String path) throws IOException { - try { + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + try + { // FIXME: Think of a better way of implementing this, so closing this will close on the computer. - return this.m_filesystem.openForRead(path, Function.identity()) - .get(); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + return this.m_filesystem.openForRead( path, Function.identity() ) + .get(); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public boolean exists(@Nonnull String path) throws IOException { - try { - return this.m_filesystem.exists(path); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public boolean exists( @Nonnull String path ) throws IOException + { + try + { + return this.m_filesystem.exists( path ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public boolean isDirectory(@Nonnull String path) throws IOException { - try { - return this.m_filesystem.isDir(path); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public boolean isDirectory( @Nonnull String path ) throws IOException + { + try + { + return this.m_filesystem.isDir( path ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public long getSize(@Nonnull String path) throws IOException { - try { - return this.m_filesystem.getSize(path); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public long getSize( @Nonnull String path ) throws IOException + { + try + { + return this.m_filesystem.getSize( path ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public String combine(String path, String child) { - return this.m_filesystem.combine(path, child); + public String combine( String path, String child ) + { + return this.m_filesystem.combine( path, child ); } @Override - public void copy(String from, String to) throws IOException { - try { - this.m_filesystem.copy(from, to); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public void copy( String from, String to ) throws IOException + { + try + { + this.m_filesystem.copy( from, to ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } @Override - public void move(String from, String to) throws IOException { - try { - this.m_filesystem.move(from, to); - } catch (FileSystemException e) { - throw new IOException(e.getMessage()); + public void move( String from, String to ) throws IOException + { + try + { + this.m_filesystem.move( from, to ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); } } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/JarMount.java b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java index f272700d3..e22a7bf9b 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/JarMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java @@ -6,6 +6,15 @@ package dan200.computercraft.core.filesystem; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.io.ByteStreams; +import dan200.computercraft.api.filesystem.FileOperationException; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.core.apis.handles.ArrayByteChannel; +import dan200.computercraft.shared.util.IoUtil; + +import javax.annotation.Nonnull; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -26,17 +35,8 @@ import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import javax.annotation.Nonnull; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.io.ByteStreams; -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.core.apis.handles.ArrayByteChannel; -import dan200.computercraft.shared.util.IoUtil; - -public class JarMount implements IMount { +public class JarMount implements IMount +{ /** * Only cache files smaller than 1MiB. */ @@ -52,10 +52,10 @@ public class JarMount implements IMount { * access disk for computer startup. */ private static final Cache CONTENTS_CACHE = CacheBuilder.newBuilder() - .concurrencyLevel(4) - .expireAfterAccess(60, TimeUnit.SECONDS) - .maximumWeight(MAX_CACHE_SIZE) - .weakKeys().weigher((k, v) -> v.length).build(); + .concurrencyLevel( 4 ) + .expireAfterAccess( 60, TimeUnit.SECONDS ) + .maximumWeight( MAX_CACHE_SIZE ) + .weakKeys().weigher( ( k, v ) -> v.length ).build(); /** * We have a {@link ReferenceQueue} of all mounts, a long with their corresponding {@link ZipFile}. If the mount has been destroyed, we clean up after @@ -66,151 +66,184 @@ public class JarMount implements IMount { private final ZipFile zip; private final FileEntry root; - public JarMount(File jarFile, String subPath) throws IOException { + public JarMount( File jarFile, String subPath ) throws IOException + { // Cleanup any old mounts. It's unlikely that there will be any, but it's best to be safe. cleanup(); - if (!jarFile.exists() || jarFile.isDirectory()) { - throw new FileNotFoundException("Cannot find " + jarFile); + if( !jarFile.exists() || jarFile.isDirectory() ) + { + throw new FileNotFoundException( "Cannot find " + jarFile ); } // Open the zip file - try { - this.zip = new ZipFile(jarFile); - } catch (IOException e) { - throw new IOException("Error loading zip file", e); + try + { + this.zip = new ZipFile( jarFile ); + } + catch( IOException e ) + { + throw new IOException( "Error loading zip file", e ); } // Ensure the root entry exists. - if (this.zip.getEntry(subPath) == null) { + if( this.zip.getEntry( subPath ) == null ) + { this.zip.close(); - throw new FileNotFoundException("Zip does not contain path"); + throw new FileNotFoundException( "Zip does not contain path" ); } // We now create a weak reference to this mount. This is automatically added to the appropriate queue. - new MountReference(this); + new MountReference( this ); // Read in all the entries this.root = new FileEntry(); Enumeration zipEntries = this.zip.entries(); - while (zipEntries.hasMoreElements()) { + while( zipEntries.hasMoreElements() ) + { ZipEntry entry = zipEntries.nextElement(); String entryPath = entry.getName(); - if (!entryPath.startsWith(subPath)) { + if( !entryPath.startsWith( subPath ) ) + { continue; } - String localPath = FileSystem.toLocal(entryPath, subPath); - this.create(entry, localPath); + String localPath = FileSystem.toLocal( entryPath, subPath ); + this.create( entry, localPath ); } } - private static void cleanup() { + private static void cleanup() + { Reference next; - while ((next = MOUNT_QUEUE.poll()) != null) { - IoUtil.closeQuietly(((MountReference) next).file); + while( (next = MOUNT_QUEUE.poll()) != null ) + { + IoUtil.closeQuietly( ((MountReference) next).file ); } } - private void create(ZipEntry entry, String localPath) { + private void create( ZipEntry entry, String localPath ) + { FileEntry lastEntry = this.root; int lastIndex = 0; - while (lastIndex < localPath.length()) { - int nextIndex = localPath.indexOf('/', lastIndex); - if (nextIndex < 0) { + while( lastIndex < localPath.length() ) + { + int nextIndex = localPath.indexOf( '/', lastIndex ); + if( nextIndex < 0 ) + { nextIndex = localPath.length(); } - String part = localPath.substring(lastIndex, nextIndex); - if (lastEntry.children == null) { - lastEntry.children = new HashMap<>(0); + String part = localPath.substring( lastIndex, nextIndex ); + if( lastEntry.children == null ) + { + lastEntry.children = new HashMap<>( 0 ); } - FileEntry nextEntry = lastEntry.children.get(part); - if (nextEntry == null || !nextEntry.isDirectory()) { - lastEntry.children.put(part, nextEntry = new FileEntry()); + FileEntry nextEntry = lastEntry.children.get( part ); + if( nextEntry == null || !nextEntry.isDirectory() ) + { + lastEntry.children.put( part, nextEntry = new FileEntry() ); } lastEntry = nextEntry; lastIndex = nextIndex + 1; } - lastEntry.setup(entry); + lastEntry.setup( entry ); } @Override - public void list(@Nonnull String path, @Nonnull List contents) throws IOException { - FileEntry file = this.get(path); - if (file == null || !file.isDirectory()) { - throw new FileOperationException(path, "Not a directory"); + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + FileEntry file = this.get( path ); + if( file == null || !file.isDirectory() ) + { + throw new FileOperationException( path, "Not a directory" ); } - file.list(contents); + file.list( contents ); } @Nonnull @Override - public ReadableByteChannel openForRead(@Nonnull String path) throws IOException { - FileEntry file = this.get(path); - if (file != null && !file.isDirectory()) { - byte[] contents = CONTENTS_CACHE.getIfPresent(file); - if (contents != null) { - return new ArrayByteChannel(contents); + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + FileEntry file = this.get( path ); + if( file != null && !file.isDirectory() ) + { + byte[] contents = CONTENTS_CACHE.getIfPresent( file ); + if( contents != null ) + { + return new ArrayByteChannel( contents ); } - try { - ZipEntry entry = this.zip.getEntry(file.path); - if (entry != null) { - try (InputStream stream = this.zip.getInputStream(entry)) { - if (stream.available() > MAX_CACHED_SIZE) { - return Channels.newChannel(stream); + try + { + ZipEntry entry = this.zip.getEntry( file.path ); + if( entry != null ) + { + try( InputStream stream = this.zip.getInputStream( entry ) ) + { + if( stream.available() > MAX_CACHED_SIZE ) + { + return Channels.newChannel( stream ); } - contents = ByteStreams.toByteArray(stream); - CONTENTS_CACHE.put(file, contents); - return new ArrayByteChannel(contents); + contents = ByteStreams.toByteArray( stream ); + CONTENTS_CACHE.put( file, contents ); + return new ArrayByteChannel( contents ); } } - } catch (IOException e) { + } + catch( IOException e ) + { // Treat errors as non-existence of file } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } @Nonnull @Override - public BasicFileAttributes getAttributes(@Nonnull String path) throws IOException { - FileEntry file = this.get(path); - if (file != null) { - ZipEntry entry = this.zip.getEntry(file.path); - if (entry != null) { - return new ZipEntryAttributes(entry); + public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException + { + FileEntry file = this.get( path ); + if( file != null ) + { + ZipEntry entry = this.zip.getEntry( file.path ); + if( entry != null ) + { + return new ZipEntryAttributes( entry ); } } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } @Override - public boolean exists(@Nonnull String path) { - return this.get(path) != null; + public boolean exists( @Nonnull String path ) + { + return this.get( path ) != null; } - private FileEntry get(String path) { + private FileEntry get( String path ) + { FileEntry lastEntry = this.root; int lastIndex = 0; - while (lastEntry != null && lastIndex < path.length()) { - int nextIndex = path.indexOf('/', lastIndex); - if (nextIndex < 0) { + while( lastEntry != null && lastIndex < path.length() ) + { + int nextIndex = path.indexOf( '/', lastIndex ); + if( nextIndex < 0 ) + { nextIndex = path.length(); } - lastEntry = lastEntry.children == null ? null : lastEntry.children.get(path.substring(lastIndex, nextIndex)); + lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); lastIndex = nextIndex + 1; } @@ -218,108 +251,132 @@ public class JarMount implements IMount { } @Override - public boolean isDirectory(@Nonnull String path) { - FileEntry file = this.get(path); + public boolean isDirectory( @Nonnull String path ) + { + FileEntry file = this.get( path ); return file != null && file.isDirectory(); } @Override - public long getSize(@Nonnull String path) throws IOException { - FileEntry file = this.get(path); - if (file != null) { + public long getSize( @Nonnull String path ) throws IOException + { + FileEntry file = this.get( path ); + if( file != null ) + { return file.size; } - throw new FileOperationException(path, "No such file"); + throw new FileOperationException( path, "No such file" ); } - private static class FileEntry { + private static class FileEntry + { String path; long size; Map children; - void setup(ZipEntry entry) { + void setup( ZipEntry entry ) + { this.path = entry.getName(); this.size = entry.getSize(); - if (this.children == null && entry.isDirectory()) { - this.children = new HashMap<>(0); + if( this.children == null && entry.isDirectory() ) + { + this.children = new HashMap<>( 0 ); } } - boolean isDirectory() { + boolean isDirectory() + { return this.children != null; } - void list(List contents) { - if (this.children != null) { - contents.addAll(this.children.keySet()); + void list( List contents ) + { + if( this.children != null ) + { + contents.addAll( this.children.keySet() ); } } } - private static class MountReference extends WeakReference { + private static class MountReference extends WeakReference + { final ZipFile file; - MountReference(JarMount file) { - super(file, MOUNT_QUEUE); + MountReference( JarMount file ) + { + super( file, MOUNT_QUEUE ); this.file = file.zip; } } - private static class ZipEntryAttributes implements BasicFileAttributes { - private static final FileTime EPOCH = FileTime.from(Instant.EPOCH); + private static class ZipEntryAttributes implements BasicFileAttributes + { + private static final FileTime EPOCH = FileTime.from( Instant.EPOCH ); private final ZipEntry entry; - ZipEntryAttributes(ZipEntry entry) { + ZipEntryAttributes( ZipEntry entry ) + { this.entry = entry; - } @Override - public FileTime lastModifiedTime() { - return orEpoch(this.entry.getLastModifiedTime()); } @Override - public FileTime lastAccessTime() { - return orEpoch(this.entry.getLastAccessTime()); + public FileTime lastModifiedTime() + { + return orEpoch( this.entry.getLastModifiedTime() ); } @Override - public FileTime creationTime() { + public FileTime lastAccessTime() + { + return orEpoch( this.entry.getLastAccessTime() ); + } + + @Override + public FileTime creationTime() + { FileTime time = this.entry.getCreationTime(); return time == null ? this.lastModifiedTime() : time; } @Override - public boolean isRegularFile() { + public boolean isRegularFile() + { return !this.entry.isDirectory(); } @Override - public boolean isDirectory() { + public boolean isDirectory() + { return this.entry.isDirectory(); } @Override - public boolean isSymbolicLink() { + public boolean isSymbolicLink() + { return false; } @Override - public boolean isOther() { + public boolean isOther() + { return false; } @Override - public long size() { + public long size() + { return this.entry.getSize(); } @Override - public Object fileKey() { + public Object fileKey() + { return null; } - - private static FileTime orEpoch(FileTime time) { + private static FileTime orEpoch( FileTime time ) + { return time == null ? EPOCH : time; } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java b/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java index ee77f8035..5800a421b 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java +++ b/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java @@ -6,6 +6,12 @@ package dan200.computercraft.core.filesystem; +import dan200.computercraft.api.filesystem.FileOperationException; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; @@ -14,250 +20,336 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import java.util.OptionalLong; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; - -class MountWrapper { +class MountWrapper +{ private final String label; private final String location; private final IMount mount; private final IWritableMount writableMount; - MountWrapper(String label, String location, IMount mount) { + MountWrapper( String label, String location, IMount mount ) + { this.label = label; this.location = location; this.mount = mount; this.writableMount = null; } - MountWrapper(String label, String location, IWritableMount mount) { + MountWrapper( String label, String location, IWritableMount mount ) + { this.label = label; this.location = location; this.mount = mount; this.writableMount = mount; } - public String getLabel() { + public String getLabel() + { return this.label; } - public String getLocation() { + public String getLocation() + { return this.location; } - public long getFreeSpace() { - if (this.writableMount == null) { + public long getFreeSpace() + { + if( this.writableMount == null ) + { return 0; } - try { + try + { return this.writableMount.getRemainingSpace(); - } catch (IOException e) { + } + catch( IOException e ) + { return 0; } } - public OptionalLong getCapacity() { + public OptionalLong getCapacity() + { return this.writableMount == null ? OptionalLong.empty() : this.writableMount.getCapacity(); } - public boolean isReadOnly(String path) { + public boolean isReadOnly( String path ) + { return this.writableMount == null; } - public boolean exists(String path) throws FileSystemException { - path = this.toLocal(path); - try { - return this.mount.exists(path); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + public boolean exists( String path ) throws FileSystemException + { + path = this.toLocal( path ); + try + { + return this.mount.exists( path ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - private String toLocal(String path) { - return FileSystem.toLocal(path, this.location); + private String toLocal( String path ) + { + return FileSystem.toLocal( path, this.location ); } - private FileSystemException localExceptionOf(@Nullable String localPath, @Nonnull IOException e) { - if (!this.location.isEmpty() && e instanceof FileOperationException) { + private FileSystemException localExceptionOf( @Nullable String localPath, @Nonnull IOException e ) + { + if( !this.location.isEmpty() && e instanceof FileOperationException ) + { FileOperationException ex = (FileOperationException) e; - if (ex.getFilename() != null) { - return this.localExceptionOf(ex.getFilename(), ex.getMessage()); + if( ex.getFilename() != null ) + { + return this.localExceptionOf( ex.getFilename(), ex.getMessage() ); } } - if (e instanceof java.nio.file.FileSystemException) { + if( e instanceof java.nio.file.FileSystemException ) + { // This error will contain the absolute path, leaking information about where MC is installed. We drop that, // just taking the reason. We assume that the error refers to the input path. String message = ((java.nio.file.FileSystemException) e).getReason() - .trim(); - return localPath == null ? new FileSystemException(message) : this.localExceptionOf(localPath, message); + .trim(); + return localPath == null ? new FileSystemException( message ) : this.localExceptionOf( localPath, message ); } - return new FileSystemException(e.getMessage()); + return new FileSystemException( e.getMessage() ); } - private FileSystemException localExceptionOf(String path, String message) { - if (!this.location.isEmpty()) { + private FileSystemException localExceptionOf( String path, String message ) + { + if( !this.location.isEmpty() ) + { path = path.isEmpty() ? this.location : this.location + "/" + path; } - return exceptionOf(path, message); + return exceptionOf( path, message ); } - private static FileSystemException exceptionOf(String path, String message) { - return new FileSystemException("/" + path + ": " + message); + private static FileSystemException exceptionOf( String path, String message ) + { + return new FileSystemException( "/" + path + ": " + message ); } - public boolean isDirectory(String path) throws FileSystemException { - path = this.toLocal(path); - try { - return this.mount.exists(path) && this.mount.isDirectory(path); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + public boolean isDirectory( String path ) throws FileSystemException + { + path = this.toLocal( path ); + try + { + return this.mount.exists( path ) && this.mount.isDirectory( path ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - public void list(String path, List contents) throws FileSystemException { - path = this.toLocal(path); - try { - if (!this.mount.exists(path) || !this.mount.isDirectory(path)) { - throw this.localExceptionOf(path, "Not a directory"); + public void list( String path, List contents ) throws FileSystemException + { + path = this.toLocal( path ); + try + { + if( !this.mount.exists( path ) || !this.mount.isDirectory( path ) ) + { + throw this.localExceptionOf( path, "Not a directory" ); } - this.mount.list(path, contents); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + this.mount.list( path, contents ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - public long getSize(String path) throws FileSystemException { - path = this.toLocal(path); - try { - if (!this.mount.exists(path)) { - throw this.localExceptionOf(path, "No such file"); + public long getSize( String path ) throws FileSystemException + { + path = this.toLocal( path ); + try + { + if( !this.mount.exists( path ) ) + { + throw this.localExceptionOf( path, "No such file" ); } - return this.mount.isDirectory(path) ? 0 : this.mount.getSize(path); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + return this.mount.isDirectory( path ) ? 0 : this.mount.getSize( path ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } @Nonnull - public BasicFileAttributes getAttributes(String path) throws FileSystemException { - path = this.toLocal(path); - try { - if (!this.mount.exists(path)) { - throw this.localExceptionOf(path, "No such file"); + public BasicFileAttributes getAttributes( String path ) throws FileSystemException + { + path = this.toLocal( path ); + try + { + if( !this.mount.exists( path ) ) + { + throw this.localExceptionOf( path, "No such file" ); } - return this.mount.getAttributes(path); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + return this.mount.getAttributes( path ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - public ReadableByteChannel openForRead(String path) throws FileSystemException { - path = this.toLocal(path); - try { - if (this.mount.exists(path) && !this.mount.isDirectory(path)) { - return this.mount.openForRead(path); - } else { - throw this.localExceptionOf(path, "No such file"); + public ReadableByteChannel openForRead( String path ) throws FileSystemException + { + path = this.toLocal( path ); + try + { + if( this.mount.exists( path ) && !this.mount.isDirectory( path ) ) + { + return this.mount.openForRead( path ); } - } catch (IOException e) { - throw this.localExceptionOf(path, e); + else + { + throw this.localExceptionOf( path, "No such file" ); + } + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - public void makeDirectory(String path) throws FileSystemException { - if (this.writableMount == null) { - throw exceptionOf(path, "Access denied"); + public void makeDirectory( String path ) throws FileSystemException + { + if( this.writableMount == null ) + { + throw exceptionOf( path, "Access denied" ); } - path = this.toLocal(path); - try { - if (this.mount.exists(path)) { - if (!this.mount.isDirectory(path)) { - throw this.localExceptionOf(path, "File exists"); + path = this.toLocal( path ); + try + { + if( this.mount.exists( path ) ) + { + if( !this.mount.isDirectory( path ) ) + { + throw this.localExceptionOf( path, "File exists" ); } - } else { - this.writableMount.makeDirectory(path); } - } catch (IOException e) { - throw this.localExceptionOf(path, e); + else + { + this.writableMount.makeDirectory( path ); + } + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - public void delete(String path) throws FileSystemException { - if (this.writableMount == null) { - throw exceptionOf(path, "Access denied"); + public void delete( String path ) throws FileSystemException + { + if( this.writableMount == null ) + { + throw exceptionOf( path, "Access denied" ); } - path = this.toLocal(path); - try { - if (this.mount.exists(path)) { - this.writableMount.delete(path); + path = this.toLocal( path ); + try + { + if( this.mount.exists( path ) ) + { + this.writableMount.delete( path ); } - } catch (AccessDeniedException e) { - throw new FileSystemException("Access denied"); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + } + catch( AccessDeniedException e ) + { + throw new FileSystemException( "Access denied" ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - public WritableByteChannel openForWrite(String path) throws FileSystemException { - if (this.writableMount == null) { - throw exceptionOf(path, "Access denied"); + public WritableByteChannel openForWrite( String path ) throws FileSystemException + { + if( this.writableMount == null ) + { + throw exceptionOf( path, "Access denied" ); } - path = this.toLocal(path); - try { - if (this.mount.exists(path) && this.mount.isDirectory(path)) { - throw this.localExceptionOf(path, "Cannot write to directory"); - } else { - if (!path.isEmpty()) { - String dir = FileSystem.getDirectory(path); - if (!dir.isEmpty() && !this.mount.exists(path)) { - this.writableMount.makeDirectory(dir); + path = this.toLocal( path ); + try + { + if( this.mount.exists( path ) && this.mount.isDirectory( path ) ) + { + throw this.localExceptionOf( path, "Cannot write to directory" ); + } + else + { + if( !path.isEmpty() ) + { + String dir = FileSystem.getDirectory( path ); + if( !dir.isEmpty() && !this.mount.exists( path ) ) + { + this.writableMount.makeDirectory( dir ); } } - return this.writableMount.openForWrite(path); + return this.writableMount.openForWrite( path ); } - } catch (AccessDeniedException e) { - throw new FileSystemException("Access denied"); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + } + catch( AccessDeniedException e ) + { + throw new FileSystemException( "Access denied" ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } - public WritableByteChannel openForAppend(String path) throws FileSystemException { - if (this.writableMount == null) { - throw exceptionOf(path, "Access denied"); + public WritableByteChannel openForAppend( String path ) throws FileSystemException + { + if( this.writableMount == null ) + { + throw exceptionOf( path, "Access denied" ); } - path = this.toLocal(path); - try { - if (!this.mount.exists(path)) { - if (!path.isEmpty()) { - String dir = FileSystem.getDirectory(path); - if (!dir.isEmpty() && !this.mount.exists(path)) { - this.writableMount.makeDirectory(dir); + path = this.toLocal( path ); + try + { + if( !this.mount.exists( path ) ) + { + if( !path.isEmpty() ) + { + String dir = FileSystem.getDirectory( path ); + if( !dir.isEmpty() && !this.mount.exists( path ) ) + { + this.writableMount.makeDirectory( dir ); } } - return this.writableMount.openForWrite(path); - } else if (this.mount.isDirectory(path)) { - throw this.localExceptionOf(path, "Cannot write to directory"); - } else { - return this.writableMount.openForAppend(path); + return this.writableMount.openForWrite( path ); } - } catch (AccessDeniedException e) { - throw new FileSystemException("Access denied"); - } catch (IOException e) { - throw this.localExceptionOf(path, e); + else if( this.mount.isDirectory( path ) ) + { + throw this.localExceptionOf( path, "Cannot write to directory" ); + } + else + { + return this.writableMount.openForAppend( path ); + } + } + catch( AccessDeniedException e ) + { + throw new FileSystemException( "Access denied" ); + } + catch( IOException e ) + { + throw this.localExceptionOf( path, e ); } } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java index 1ae391738..d60dd8ff2 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java @@ -6,24 +6,6 @@ package dan200.computercraft.core.filesystem; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.MapMaker; @@ -40,7 +22,20 @@ import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; import net.minecraft.util.profiler.Profiler; -public final class ResourceMount implements IMount { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; + +public final class ResourceMount implements IMount +{ /** * Only cache files smaller than 1MiB. */ @@ -58,37 +53,41 @@ public final class ResourceMount implements IMount { * access disk for computer startup. */ private static final Cache CONTENTS_CACHE = CacheBuilder.newBuilder() - .concurrencyLevel(4) - .expireAfterAccess(60, TimeUnit.SECONDS) - .maximumWeight(MAX_CACHE_SIZE) - .weakKeys().weigher((k, v) -> v.length).build(); + .concurrencyLevel( 4 ) + .expireAfterAccess( 60, TimeUnit.SECONDS ) + .maximumWeight( MAX_CACHE_SIZE ) + .weakKeys().weigher( ( k, v ) -> v.length ).build(); private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues() - .concurrencyLevel(1); + .concurrencyLevel( 1 ); /** * Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes. */ - private static final Map> MOUNT_CACHE = new WeakHashMap<>(2); + private static final Map> MOUNT_CACHE = new WeakHashMap<>( 2 ); private final String namespace; private final String subPath; private final ReloadableResourceManager manager; - @Nullable private FileEntry root; + @Nullable + private FileEntry root; - private ResourceMount(String namespace, String subPath, ReloadableResourceManager manager) { + private ResourceMount( String namespace, String subPath, ReloadableResourceManager manager ) + { this.namespace = namespace; this.subPath = subPath; this.manager = manager; - Listener.INSTANCE.add(manager, this); - if (this.root == null) { + Listener.INSTANCE.add( manager, this ); + if( this.root == null ) + { this.load(); } } - private void load() { + private void load() + { boolean hasAny = false; String existingNamespace = null; @@ -99,8 +98,8 @@ public final class ResourceMount implements IMount { if( !file.getNamespace().equals( namespace ) ) continue; - String localPath = FileSystem.toLocal(file.getPath(), this.subPath); - this.create(newRoot, localPath); + String localPath = FileSystem.toLocal( file.getPath(), this.subPath ); + this.create( newRoot, localPath ); hasAny = true; } @@ -111,34 +110,42 @@ public final class ResourceMount implements IMount { ComputerCraft.log.warn( "Cannot find any files under /data/{}/{} for resource mount.", namespace, subPath ); if( existingNamespace != null ) { - ComputerCraft.log.warn("There are files under /data/{}/{} though. Did you get the wrong namespace?", existingNamespace, subPath); + ComputerCraft.log.warn( "There are files under /data/{}/{} though. Did you get the wrong namespace?", existingNamespace, subPath ); } } } - private void create(FileEntry lastEntry, String path) { + private void create( FileEntry lastEntry, String path ) + { int lastIndex = 0; - while (lastIndex < path.length()) { - int nextIndex = path.indexOf('/', lastIndex); - if (nextIndex < 0) { + while( lastIndex < path.length() ) + { + int nextIndex = path.indexOf( '/', lastIndex ); + if( nextIndex < 0 ) + { nextIndex = path.length(); } - String part = path.substring(lastIndex, nextIndex); - if (lastEntry.children == null) { + String part = path.substring( lastIndex, nextIndex ); + if( lastEntry.children == null ) + { lastEntry.children = new HashMap<>(); } - FileEntry nextEntry = lastEntry.children.get(part); - if (nextEntry == null) { + FileEntry nextEntry = lastEntry.children.get( part ); + if( nextEntry == null ) + { Identifier childPath; - try { - childPath = new Identifier(this.namespace, this.subPath + "/" + path); - } catch (InvalidIdentifierException e) { - ComputerCraft.log.warn("Cannot create resource location for {} ({})", part, e.getMessage()); + try + { + childPath = new Identifier( this.namespace, this.subPath + "/" + path ); + } + catch( InvalidIdentifierException e ) + { + ComputerCraft.log.warn( "Cannot create resource location for {} ({})", part, e.getMessage() ); return; } - lastEntry.children.put(part, nextEntry = new FileEntry(childPath)); + lastEntry.children.put( part, nextEntry = new FileEntry( childPath ) ); } lastEntry = nextEntry; @@ -146,44 +153,54 @@ public final class ResourceMount implements IMount { } } - public static ResourceMount get(String namespace, String subPath, ReloadableResourceManager manager) { + public static ResourceMount get( String namespace, String subPath, ReloadableResourceManager manager ) + { Map cache; - synchronized (MOUNT_CACHE) { - cache = MOUNT_CACHE.get(manager); - if (cache == null) { - MOUNT_CACHE.put(manager, cache = CACHE_TEMPLATE.makeMap()); + synchronized( MOUNT_CACHE ) + { + cache = MOUNT_CACHE.get( manager ); + if( cache == null ) + { + MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() ); } } - Identifier path = new Identifier(namespace, subPath); - synchronized (cache) { - ResourceMount mount = cache.get(path); - if (mount == null) { - cache.put(path, mount = new ResourceMount(namespace, subPath, manager)); + Identifier path = new Identifier( namespace, subPath ); + synchronized( cache ) + { + ResourceMount mount = cache.get( path ); + if( mount == null ) + { + cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) ); } return mount; } } @Override - public void list(@Nonnull String path, @Nonnull List contents) throws IOException { - FileEntry file = this.get(path); - if (file == null || !file.isDirectory()) { - throw new IOException("/" + path + ": Not a directory"); + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + FileEntry file = this.get( path ); + if( file == null || !file.isDirectory() ) + { + throw new IOException( "/" + path + ": Not a directory" ); } - file.list(contents); + file.list( contents ); } @Nonnull @Override - public ReadableByteChannel openForRead(@Nonnull String path) throws IOException { - FileEntry file = this.get(path); - if (file != null && !file.isDirectory()) { - byte[] contents = CONTENTS_CACHE.getIfPresent(file); - if (contents != null) { - return new ArrayByteChannel(contents); + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + FileEntry file = this.get( path ); + if( file != null && !file.isDirectory() ) + { + byte[] contents = CONTENTS_CACHE.getIfPresent( file ); + if( contents != null ) + { + return new ArrayByteChannel( contents ); } try @@ -199,31 +216,37 @@ public final class ResourceMount implements IMount { { IoUtil.closeQuietly( stream ); } - CONTENTS_CACHE.put(file, contents); - return new ArrayByteChannel(contents); - } catch (FileNotFoundException ignored) { + CONTENTS_CACHE.put( file, contents ); + return new ArrayByteChannel( contents ); + } + catch( FileNotFoundException ignored ) + { } } - throw new IOException("/" + path + ": No such file"); + throw new IOException( "/" + path + ": No such file" ); } @Override - public boolean exists(@Nonnull String path) { - return this.get(path) != null; + public boolean exists( @Nonnull String path ) + { + return this.get( path ) != null; } - private FileEntry get(String path) { + private FileEntry get( String path ) + { FileEntry lastEntry = this.root; int lastIndex = 0; - while (lastEntry != null && lastIndex < path.length()) { - int nextIndex = path.indexOf('/', lastIndex); - if (nextIndex < 0) { + while( lastEntry != null && lastIndex < path.length() ) + { + int nextIndex = path.indexOf( '/', lastIndex ); + if( nextIndex < 0 ) + { nextIndex = path.length(); } - lastEntry = lastEntry.children == null ? null : lastEntry.children.get(path.substring(lastIndex, nextIndex)); + lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); lastIndex = nextIndex + 1; } @@ -231,61 +254,76 @@ public final class ResourceMount implements IMount { } @Override - public boolean isDirectory(@Nonnull String path) { - FileEntry file = this.get(path); + public boolean isDirectory( @Nonnull String path ) + { + FileEntry file = this.get( path ); return file != null && file.isDirectory(); } @Override - public long getSize(@Nonnull String path) throws IOException { - FileEntry file = this.get(path); - if (file != null) { - if (file.size != -1) { + public long getSize( @Nonnull String path ) throws IOException + { + FileEntry file = this.get( path ); + if( file != null ) + { + if( file.size != -1 ) + { return file.size; } - if (file.isDirectory()) { + if( file.isDirectory() ) + { return file.size = 0; } - byte[] contents = CONTENTS_CACHE.getIfPresent(file); - if (contents != null) { + byte[] contents = CONTENTS_CACHE.getIfPresent( file ); + if( contents != null ) + { return file.size = contents.length; } - try { - Resource resource = this.manager.getResource(file.identifier); + try + { + Resource resource = this.manager.getResource( file.identifier ); InputStream s = resource.getInputStream(); int total = 0, read = 0; - do { + do + { total += read; - read = s.read(TEMP_BUFFER); - } while (read > 0); + read = s.read( TEMP_BUFFER ); + } while( read > 0 ); return file.size = total; - } catch (IOException e) { + } + catch( IOException e ) + { return file.size = 0; } } - throw new IOException("/" + path + ": No such file"); + throw new IOException( "/" + path + ": No such file" ); } - private static class FileEntry { + private static class FileEntry + { final Identifier identifier; Map children; long size = -1; - FileEntry(Identifier identifier) { + FileEntry( Identifier identifier ) + { this.identifier = identifier; } - boolean isDirectory() { + boolean isDirectory() + { return this.children != null; } - void list(List contents) { - if (this.children != null) { - contents.addAll(this.children.keySet()); + void list( List contents ) + { + if( this.children != null ) + { + contents.addAll( this.children.keySet() ); } } } @@ -294,32 +332,40 @@ public final class ResourceMount implements IMount { * While people should really be keeping a permanent reference to this, some people construct it every method call, so let's make this as small as * possible. */ - static class Listener implements ResourceReloadListener { + static class Listener implements ResourceReloadListener + { private static final Listener INSTANCE = new Listener(); - private final Set mounts = Collections.newSetFromMap(new WeakHashMap<>()); - private final Set managers = Collections.newSetFromMap(new WeakHashMap<>()); + private final Set mounts = Collections.newSetFromMap( new WeakHashMap<>() ); + private final Set managers = Collections.newSetFromMap( new WeakHashMap<>() ); @Override - public CompletableFuture reload(Synchronizer synchronizer, ResourceManager resourceManager, Profiler profiler, Profiler profiler1, - Executor executor, Executor executor1) { - return CompletableFuture.runAsync(() -> { - profiler.push("Mount reloading"); - try { - for (ResourceMount mount : this.mounts) { + public CompletableFuture reload( Synchronizer synchronizer, ResourceManager resourceManager, Profiler profiler, Profiler profiler1, + Executor executor, Executor executor1 ) + { + return CompletableFuture.runAsync( () -> { + profiler.push( "Mount reloading" ); + try + { + for( ResourceMount mount : this.mounts ) + { mount.load(); } - } finally { + } + finally + { profiler.pop(); } - }, executor); + }, executor ); } - synchronized void add(ReloadableResourceManager manager, ResourceMount mount) { - if (this.managers.add(manager)) { - manager.registerListener(this); + synchronized void add( ReloadableResourceManager manager, ResourceMount mount ) + { + if( this.managers.add( manager ) ) + { + manager.registerListener( this ); } - this.mounts.add(mount); + this.mounts.add( mount ); } } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/SubMount.java b/src/main/java/dan200/computercraft/core/filesystem/SubMount.java index 4bba07366..1eb05f841 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/SubMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/SubMount.java @@ -6,57 +6,65 @@ package dan200.computercraft.core.filesystem; +import dan200.computercraft.api.filesystem.IMount; + +import javax.annotation.Nonnull; import java.io.IOException; import java.nio.channels.ReadableByteChannel; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; -import javax.annotation.Nonnull; - -import dan200.computercraft.api.filesystem.IMount; - -public class SubMount implements IMount { +public class SubMount implements IMount +{ private IMount parent; private String subPath; - public SubMount(IMount parent, String subPath) { + public SubMount( IMount parent, String subPath ) + { this.parent = parent; this.subPath = subPath; } @Override - public void list(@Nonnull String path, @Nonnull List contents) throws IOException { - this.parent.list(this.getFullPath(path), contents); + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + this.parent.list( this.getFullPath( path ), contents ); } @Nonnull @Override - public ReadableByteChannel openForRead(@Nonnull String path) throws IOException { - return this.parent.openForRead(this.getFullPath(path)); + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + return this.parent.openForRead( this.getFullPath( path ) ); } @Nonnull @Override - public BasicFileAttributes getAttributes(@Nonnull String path) throws IOException { - return this.parent.getAttributes(this.getFullPath(path)); + public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException + { + return this.parent.getAttributes( this.getFullPath( path ) ); } @Override - public boolean exists(@Nonnull String path) throws IOException { - return this.parent.exists(this.getFullPath(path)); + public boolean exists( @Nonnull String path ) throws IOException + { + return this.parent.exists( this.getFullPath( path ) ); } @Override - public boolean isDirectory(@Nonnull String path) throws IOException { - return this.parent.isDirectory(this.getFullPath(path)); + public boolean isDirectory( @Nonnull String path ) throws IOException + { + return this.parent.isDirectory( this.getFullPath( path ) ); } @Override - public long getSize(@Nonnull String path) throws IOException { - return this.parent.getSize(this.getFullPath(path)); + public long getSize( @Nonnull String path ) throws IOException + { + return this.parent.getSize( this.getFullPath( path ) ); } - private String getFullPath(String path) { + private String getFullPath( String path ) + { return path.isEmpty() ? this.subPath : this.subPath + "/" + path; } } diff --git a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java index 6b2dd4d4b..edb8f695d 100644 --- a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java @@ -21,14 +21,16 @@ import org.squiddev.cobalt.function.VarArgFunction; * * As we never yield, we do not need to push a function to the stack, which removes a small amount of overhead. */ -class BasicFunction extends VarArgFunction { +class BasicFunction extends VarArgFunction +{ private final CobaltLuaMachine machine; private final LuaMethod method; private final Object instance; private final ILuaContext context; private final String name; - BasicFunction(CobaltLuaMachine machine, LuaMethod method, Object instance, ILuaContext context, String name) { + BasicFunction( CobaltLuaMachine machine, LuaMethod method, Object instance, ILuaContext context, String name ) + { this.machine = machine; this.method = method; this.instance = instance; @@ -37,27 +39,36 @@ class BasicFunction extends VarArgFunction { } @Override - public Varargs invoke(LuaState luaState, Varargs args) throws LuaError { - IArguments arguments = CobaltLuaMachine.toArguments(args); + public Varargs invoke( LuaState luaState, Varargs args ) throws LuaError + { + IArguments arguments = CobaltLuaMachine.toArguments( args ); MethodResult results; - try { - results = this.method.apply(this.instance, this.context, arguments); - } catch (LuaException e) { - throw wrap(e); - } catch (Throwable t) { - if (ComputerCraft.logComputerErrors) { - ComputerCraft.log.error("Error calling " + this.name + " on " + this.instance, t); + try + { + results = this.method.apply( this.instance, this.context, arguments ); + } + catch( LuaException e ) + { + throw wrap( e ); + } + catch( Throwable t ) + { + if( ComputerCraft.logComputerErrors ) + { + ComputerCraft.log.error( "Error calling " + this.name + " on " + this.instance, t ); } - throw new LuaError("Java Exception Thrown: " + t, 0); + throw new LuaError( "Java Exception Thrown: " + t, 0 ); } - if (results.getCallback() != null) { - throw new IllegalStateException("Cannot have a yielding non-yielding function"); + if( results.getCallback() != null ) + { + throw new IllegalStateException( "Cannot have a yielding non-yielding function" ); } - return this.machine.toValues(results.getResult()); + return this.machine.toValues( results.getResult() ); } - public static LuaError wrap(LuaException exception) { - return exception.hasLevel() ? new LuaError(exception.getMessage()) : new LuaError(exception.getMessage(), exception.getLevel()); + public static LuaError wrap( LuaException exception ) + { + return exception.hasLevel() ? new LuaError( exception.getMessage() ) : new LuaError( exception.getMessage(), exception.getLevel() ); } } diff --git a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java index 486a59244..93d6b3737 100644 --- a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java +++ b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java @@ -6,34 +6,8 @@ package dan200.computercraft.core.lua; -import static org.squiddev.cobalt.ValueFactory.valueOf; -import static org.squiddev.cobalt.ValueFactory.varargsOf; -import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKED; -import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKYIELD; - -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.IDynamicLuaObject; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.ILuaFunction; -import dan200.computercraft.api.lua.ILuaTask; -import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.*; import dan200.computercraft.core.asm.LuaMethod; import dan200.computercraft.core.asm.ObjectSource; import dan200.computercraft.core.computer.Computer; @@ -42,39 +16,40 @@ import dan200.computercraft.core.computer.TimeoutState; import dan200.computercraft.core.tracking.Tracking; import dan200.computercraft.core.tracking.TrackingField; import dan200.computercraft.shared.util.ThreadUtils; -import org.squiddev.cobalt.Constants; -import org.squiddev.cobalt.LuaError; -import org.squiddev.cobalt.LuaState; -import org.squiddev.cobalt.LuaTable; -import org.squiddev.cobalt.LuaThread; -import org.squiddev.cobalt.LuaValue; -import org.squiddev.cobalt.UnwindThrowable; -import org.squiddev.cobalt.Varargs; +import org.squiddev.cobalt.*; import org.squiddev.cobalt.compiler.CompileException; import org.squiddev.cobalt.compiler.LoadState; import org.squiddev.cobalt.debug.DebugFrame; import org.squiddev.cobalt.debug.DebugHandler; import org.squiddev.cobalt.debug.DebugState; import org.squiddev.cobalt.function.LuaFunction; -import org.squiddev.cobalt.lib.BaseLib; -import org.squiddev.cobalt.lib.Bit32Lib; -import org.squiddev.cobalt.lib.CoroutineLib; -import org.squiddev.cobalt.lib.DebugLib; -import org.squiddev.cobalt.lib.MathLib; -import org.squiddev.cobalt.lib.StringLib; -import org.squiddev.cobalt.lib.TableLib; -import org.squiddev.cobalt.lib.Utf8Lib; +import org.squiddev.cobalt.lib.*; import org.squiddev.cobalt.lib.platform.VoidResourceManipulator; -public class CobaltLuaMachine implements ILuaMachine { - private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor(0, - Integer.MAX_VALUE, - 5L, - TimeUnit.MINUTES, - new SynchronousQueue<>(), - ThreadUtils.factory("Coroutine")); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.*; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; - private static final LuaMethod FUNCTION_METHOD = (target, context, args) -> ((ILuaFunction) target).call(args); +import static org.squiddev.cobalt.ValueFactory.valueOf; +import static org.squiddev.cobalt.ValueFactory.varargsOf; +import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKED; +import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKYIELD; + +public class CobaltLuaMachine implements ILuaMachine +{ + private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor( 0, + Integer.MAX_VALUE, + 5L, + TimeUnit.MINUTES, + new SynchronousQueue<>(), + ThreadUtils.factory( "Coroutine" ) ); + + private static final LuaMethod FUNCTION_METHOD = ( target, context, args ) -> ((ILuaFunction) target).call( args ); private final Computer m_computer; private final TimeoutState timeout; @@ -87,225 +62,275 @@ public class CobaltLuaMachine implements ILuaMachine { private LuaThread m_mainRoutine = null; private String m_eventFilter = null; - public CobaltLuaMachine(Computer computer, TimeoutState timeout) { + public CobaltLuaMachine( Computer computer, TimeoutState timeout ) + { this.m_computer = computer; this.timeout = timeout; this.debug = new TimeoutDebugHandler(); // Create an environment to run in LuaState state = this.m_state = LuaState.builder() - .resourceManipulator(new VoidResourceManipulator()) - .debug(this.debug) - .coroutineExecutor(command -> { - Tracking.addValue(this.m_computer, TrackingField.COROUTINES_CREATED, 1); - COROUTINES.execute(() -> { - try { - command.run(); - } finally { - Tracking.addValue(this.m_computer, TrackingField.COROUTINES_DISPOSED, 1); - } - }); - }) - .build(); + .resourceManipulator( new VoidResourceManipulator() ) + .debug( this.debug ) + .coroutineExecutor( command -> { + Tracking.addValue( this.m_computer, TrackingField.COROUTINES_CREATED, 1 ); + COROUTINES.execute( () -> { + try + { + command.run(); + } + finally + { + Tracking.addValue( this.m_computer, TrackingField.COROUTINES_DISPOSED, 1 ); + } + } ); + } ) + .build(); this.m_globals = new LuaTable(); - state.setupThread(this.m_globals); + state.setupThread( this.m_globals ); // Add basic libraries - this.m_globals.load(state, new BaseLib()); - this.m_globals.load(state, new TableLib()); - this.m_globals.load(state, new StringLib()); - this.m_globals.load(state, new MathLib()); - this.m_globals.load(state, new CoroutineLib()); - this.m_globals.load(state, new Bit32Lib()); - this.m_globals.load(state, new Utf8Lib()); - if (ComputerCraft.debugEnable) { - this.m_globals.load(state, new DebugLib()); + this.m_globals.load( state, new BaseLib() ); + this.m_globals.load( state, new TableLib() ); + this.m_globals.load( state, new StringLib() ); + this.m_globals.load( state, new MathLib() ); + this.m_globals.load( state, new CoroutineLib() ); + this.m_globals.load( state, new Bit32Lib() ); + this.m_globals.load( state, new Utf8Lib() ); + if( ComputerCraft.debugEnable ) + { + this.m_globals.load( state, new DebugLib() ); } // Remove globals we don't want to expose - this.m_globals.rawset("collectgarbage", Constants.NIL); - this.m_globals.rawset("dofile", Constants.NIL); - this.m_globals.rawset("loadfile", Constants.NIL); - this.m_globals.rawset("print", Constants.NIL); + this.m_globals.rawset( "collectgarbage", Constants.NIL ); + this.m_globals.rawset( "dofile", Constants.NIL ); + this.m_globals.rawset( "loadfile", Constants.NIL ); + this.m_globals.rawset( "print", Constants.NIL ); // Add version globals - this.m_globals.rawset("_VERSION", valueOf("Lua 5.1")); - this.m_globals.rawset("_HOST", - valueOf(computer.getAPIEnvironment() - .getComputerEnvironment() - .getHostString())); - this.m_globals.rawset("_CC_DEFAULT_SETTINGS", valueOf(ComputerCraft.defaultComputerSettings)); - if (ComputerCraft.disableLua51Features) { - this.m_globals.rawset("_CC_DISABLE_LUA51_FEATURES", Constants.TRUE); + this.m_globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) ); + this.m_globals.rawset( "_HOST", + valueOf( computer.getAPIEnvironment() + .getComputerEnvironment() + .getHostString() ) ); + this.m_globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.defaultComputerSettings ) ); + if( ComputerCraft.disableLua51Features ) + { + this.m_globals.rawset( "_CC_DISABLE_LUA51_FEATURES", Constants.TRUE ); } } - static Object toObject(LuaValue value, Map objects) { - switch (value.type()) { - case Constants.TNIL: - case Constants.TNONE: - return null; - case Constants.TINT: - case Constants.TNUMBER: - return value.toDouble(); - case Constants.TBOOLEAN: - return value.toBoolean(); - case Constants.TSTRING: - return value.toString(); - case Constants.TTABLE: { - // Table: - // Start remembering stuff - if (objects == null) { - objects = new IdentityHashMap<>(1); - } else { - Object existing = objects.get(value); - if (existing != null) { - return existing; + static Object toObject( LuaValue value, Map objects ) + { + switch( value.type() ) + { + case Constants.TNIL: + case Constants.TNONE: + return null; + case Constants.TINT: + case Constants.TNUMBER: + return value.toDouble(); + case Constants.TBOOLEAN: + return value.toBoolean(); + case Constants.TSTRING: + return value.toString(); + case Constants.TTABLE: + { + // Table: + // Start remembering stuff + if( objects == null ) + { + objects = new IdentityHashMap<>( 1 ); } + else + { + Object existing = objects.get( value ); + if( existing != null ) + { + return existing; + } + } + Map table = new HashMap<>(); + objects.put( value, table ); + + LuaTable luaTable = (LuaTable) value; + + // Convert all keys + LuaValue k = Constants.NIL; + while( true ) + { + Varargs keyValue; + try + { + keyValue = luaTable.next( k ); + } + catch( LuaError luaError ) + { + break; + } + k = keyValue.first(); + if( k.isNil() ) + { + break; + } + + LuaValue v = keyValue.arg( 2 ); + Object keyObject = toObject( k, objects ); + Object valueObject = toObject( v, objects ); + if( keyObject != null && valueObject != null ) + { + table.put( keyObject, valueObject ); + } + } + return table; } - Map table = new HashMap<>(); - objects.put(value, table); - - LuaTable luaTable = (LuaTable) value; - - // Convert all keys - LuaValue k = Constants.NIL; - while (true) { - Varargs keyValue; - try { - keyValue = luaTable.next(k); - } catch (LuaError luaError) { - break; - } - k = keyValue.first(); - if (k.isNil()) { - break; - } - - LuaValue v = keyValue.arg(2); - Object keyObject = toObject(k, objects); - Object valueObject = toObject(v, objects); - if (keyObject != null && valueObject != null) { - table.put(keyObject, valueObject); - } - } - return table; - } - default: - return null; + default: + return null; } } - static Object[] toObjects(Varargs values) { + static Object[] toObjects( Varargs values ) + { int count = values.count(); Object[] objects = new Object[count]; - for (int i = 0; i < count; i++) { - objects[i] = toObject(values.arg(i + 1), null); + for( int i = 0; i < count; i++ ) + { + objects[i] = toObject( values.arg( i + 1 ), null ); } return objects; } - static IArguments toArguments(Varargs values) { - return values == Constants.NONE ? VarargArguments.EMPTY : new VarargArguments(values); + static IArguments toArguments( Varargs values ) + { + return values == Constants.NONE ? VarargArguments.EMPTY : new VarargArguments( values ); } @Override - public void addAPI(@Nonnull ILuaAPI api) { + public void addAPI( @Nonnull ILuaAPI api ) + { // Add the methods of an API to the global table - LuaTable table = this.wrapLuaObject(api); - if (table == null) { - ComputerCraft.log.warn("API {} does not provide any methods", api); + LuaTable table = this.wrapLuaObject( api ); + if( table == null ) + { + ComputerCraft.log.warn( "API {} does not provide any methods", api ); table = new LuaTable(); } String[] names = api.getNames(); - for (String name : names) { - this.m_globals.rawset(name, table); + for( String name : names ) + { + this.m_globals.rawset( name, table ); } } @Override - public MachineResult loadBios(@Nonnull InputStream bios) { + public MachineResult loadBios( @Nonnull InputStream bios ) + { // Begin executing a file (ie, the bios) - if (this.m_mainRoutine != null) { + if( this.m_mainRoutine != null ) + { return MachineResult.OK; } - try { - LuaFunction value = LoadState.load(this.m_state, bios, "@bios.lua", this.m_globals); - this.m_mainRoutine = new LuaThread(this.m_state, value, this.m_globals); + try + { + LuaFunction value = LoadState.load( this.m_state, bios, "@bios.lua", this.m_globals ); + this.m_mainRoutine = new LuaThread( this.m_state, value, this.m_globals ); return MachineResult.OK; - } catch (CompileException e) { + } + catch( CompileException e ) + { this.close(); - return MachineResult.error(e); - } catch (Exception e) { - ComputerCraft.log.warn("Could not load bios.lua", e); + return MachineResult.error( e ); + } + catch( Exception e ) + { + ComputerCraft.log.warn( "Could not load bios.lua", e ); this.close(); return MachineResult.GENERIC_ERROR; } } @Override - public MachineResult handleEvent(String eventName, Object[] arguments) { - if (this.m_mainRoutine == null) { + public MachineResult handleEvent( String eventName, Object[] arguments ) + { + if( this.m_mainRoutine == null ) + { return MachineResult.OK; } - if (this.m_eventFilter != null && eventName != null && !eventName.equals(this.m_eventFilter) && !eventName.equals("terminate")) { + if( this.m_eventFilter != null && eventName != null && !eventName.equals( this.m_eventFilter ) && !eventName.equals( "terminate" ) ) + { return MachineResult.OK; } // If the soft abort has been cleared then we can reset our flag. this.timeout.refresh(); - if (!this.timeout.isSoftAborted()) { + if( !this.timeout.isSoftAborted() ) + { this.debug.thrownSoftAbort = false; } - try { + try + { Varargs resumeArgs = Constants.NONE; - if (eventName != null) { - resumeArgs = varargsOf(valueOf(eventName), this.toValues(arguments)); + if( eventName != null ) + { + resumeArgs = varargsOf( valueOf( eventName ), this.toValues( arguments ) ); } // Resume the current thread, or the main one when first starting off. LuaThread thread = this.m_state.getCurrentThread(); - if (thread == null || thread == this.m_state.getMainThread()) { + if( thread == null || thread == this.m_state.getMainThread() ) + { thread = this.m_mainRoutine; } - Varargs results = LuaThread.run(thread, resumeArgs); - if (this.timeout.isHardAborted()) { + Varargs results = LuaThread.run( thread, resumeArgs ); + if( this.timeout.isHardAborted() ) + { throw HardAbortError.INSTANCE; } - if (results == null) { + if( results == null ) + { return MachineResult.PAUSE; } LuaValue filter = results.first(); this.m_eventFilter = filter.isString() ? filter.toString() : null; - if (this.m_mainRoutine.getStatus() - .equals("dead")) { + if( this.m_mainRoutine.getStatus() + .equals( "dead" ) ) + { this.close(); return MachineResult.GENERIC_ERROR; - } else { + } + else + { return MachineResult.OK; } - } catch (HardAbortError | InterruptedException e) { + } + catch( HardAbortError | InterruptedException e ) + { this.close(); return MachineResult.TIMEOUT; - } catch (LuaError e) { + } + catch( LuaError e ) + { this.close(); - ComputerCraft.log.warn("Top level coroutine errored", e); - return MachineResult.error(e); + ComputerCraft.log.warn( "Top level coroutine errored", e ); + return MachineResult.error( e ); } } @Override - public void close() { + public void close() + { LuaState state = this.m_state; - if (state == null) { + if( state == null ) + { return; } @@ -316,164 +341,198 @@ public class CobaltLuaMachine implements ILuaMachine { } @Nullable - private LuaTable wrapLuaObject(Object object) { - String[] dynamicMethods = object instanceof IDynamicLuaObject ? Objects.requireNonNull(((IDynamicLuaObject) object).getMethodNames(), - "Methods cannot be null") : LuaMethod.EMPTY_METHODS; + private LuaTable wrapLuaObject( Object object ) + { + String[] dynamicMethods = object instanceof IDynamicLuaObject ? Objects.requireNonNull( ((IDynamicLuaObject) object).getMethodNames(), + "Methods cannot be null" ) : LuaMethod.EMPTY_METHODS; LuaTable table = new LuaTable(); - for (int i = 0; i < dynamicMethods.length; i++) { + for( int i = 0; i < dynamicMethods.length; i++ ) + { String method = dynamicMethods[i]; - table.rawset(method, new ResultInterpreterFunction(this, LuaMethod.DYNAMIC.get(i), object, this.context, method)); + table.rawset( method, new ResultInterpreterFunction( this, LuaMethod.DYNAMIC.get( i ), object, this.context, method ) ); } - ObjectSource.allMethods(LuaMethod.GENERATOR, - object, - (instance, method) -> table.rawset(method.getName(), - method.nonYielding() ? new BasicFunction(this, - (LuaMethod) method.getMethod(), - instance, this.context, - method.getName()) : - new ResultInterpreterFunction( - this, - (LuaMethod) method.getMethod(), - instance, this.context, - method.getName()))); + ObjectSource.allMethods( LuaMethod.GENERATOR, + object, + ( instance, method ) -> table.rawset( method.getName(), + method.nonYielding() ? new BasicFunction( this, + (LuaMethod) method.getMethod(), + instance, this.context, + method.getName() ) : + new ResultInterpreterFunction( + this, + (LuaMethod) method.getMethod(), + instance, this.context, + method.getName() ) ) ); - try { - if (table.keyCount() == 0) { + try + { + if( table.keyCount() == 0 ) + { return null; } - } catch (LuaError ignored) { + } + catch( LuaError ignored ) + { } return table; } @Nonnull - private LuaValue toValue(@Nullable Object object, @Nullable Map values) { - if (object == null) { + private LuaValue toValue( @Nullable Object object, @Nullable Map values ) + { + if( object == null ) + { return Constants.NIL; } - if (object instanceof Number) { - return valueOf(((Number) object).doubleValue()); + if( object instanceof Number ) + { + return valueOf( ((Number) object).doubleValue() ); } - if (object instanceof Boolean) { - return valueOf((Boolean) object); + if( object instanceof Boolean ) + { + return valueOf( (Boolean) object ); } - if (object instanceof String) { - return valueOf(object.toString()); + if( object instanceof String ) + { + return valueOf( object.toString() ); } - if (object instanceof byte[]) { + if( object instanceof byte[] ) + { byte[] b = (byte[]) object; - return valueOf(Arrays.copyOf(b, b.length)); + return valueOf( Arrays.copyOf( b, b.length ) ); } - if (object instanceof ByteBuffer) { + if( object instanceof ByteBuffer ) + { ByteBuffer b = (ByteBuffer) object; byte[] bytes = new byte[b.remaining()]; - b.get(bytes); - return valueOf(bytes); + b.get( bytes ); + return valueOf( bytes ); } - if (values == null) { - values = new IdentityHashMap<>(1); + if( values == null ) + { + values = new IdentityHashMap<>( 1 ); } - LuaValue result = values.get(object); - if (result != null) { + LuaValue result = values.get( object ); + if( result != null ) + { return result; } - if (object instanceof ILuaFunction) { - return new ResultInterpreterFunction(this, FUNCTION_METHOD, object, this.context, object.toString()); + if( object instanceof ILuaFunction ) + { + return new ResultInterpreterFunction( this, FUNCTION_METHOD, object, this.context, object.toString() ); } - if (object instanceof IDynamicLuaObject) { - LuaValue wrapped = this.wrapLuaObject(object); - if (wrapped == null) { + if( object instanceof IDynamicLuaObject ) + { + LuaValue wrapped = this.wrapLuaObject( object ); + if( wrapped == null ) + { wrapped = new LuaTable(); } - values.put(object, wrapped); + values.put( object, wrapped ); return wrapped; } - if (object instanceof Map) { + if( object instanceof Map ) + { LuaTable table = new LuaTable(); - values.put(object, table); + values.put( object, table ); - for (Map.Entry pair : ((Map) object).entrySet()) { - LuaValue key = this.toValue(pair.getKey(), values); - LuaValue value = this.toValue(pair.getValue(), values); - if (!key.isNil() && !value.isNil()) { - table.rawset(key, value); + for( Map.Entry pair : ((Map) object).entrySet() ) + { + LuaValue key = this.toValue( pair.getKey(), values ); + LuaValue value = this.toValue( pair.getValue(), values ); + if( !key.isNil() && !value.isNil() ) + { + table.rawset( key, value ); } } return table; } - if (object instanceof Collection) { + if( object instanceof Collection ) + { Collection objects = (Collection) object; - LuaTable table = new LuaTable(objects.size(), 0); - values.put(object, table); + LuaTable table = new LuaTable( objects.size(), 0 ); + values.put( object, table ); int i = 0; - for (Object child : objects) { - table.rawset(++i, this.toValue(child, values)); + for( Object child : objects ) + { + table.rawset( ++i, this.toValue( child, values ) ); } return table; } - if (object instanceof Object[]) { + if( object instanceof Object[] ) + { Object[] objects = (Object[]) object; - LuaTable table = new LuaTable(objects.length, 0); - values.put(object, table); - for (int i = 0; i < objects.length; i++) { - table.rawset(i + 1, this.toValue(objects[i], values)); + LuaTable table = new LuaTable( objects.length, 0 ); + values.put( object, table ); + for( int i = 0; i < objects.length; i++ ) + { + table.rawset( i + 1, this.toValue( objects[i], values ) ); } return table; } - LuaTable wrapped = this.wrapLuaObject(object); - if (wrapped != null) { - values.put(object, wrapped); + LuaTable wrapped = this.wrapLuaObject( object ); + if( wrapped != null ) + { + values.put( object, wrapped ); return wrapped; } - if (ComputerCraft.logComputerErrors) { - ComputerCraft.log.warn("Received unknown type '{}', returning nil.", - object.getClass() - .getName()); + if( ComputerCraft.logComputerErrors ) + { + ComputerCraft.log.warn( "Received unknown type '{}', returning nil.", + object.getClass() + .getName() ); } return Constants.NIL; } - Varargs toValues(Object[] objects) { - if (objects == null || objects.length == 0) { + Varargs toValues( Object[] objects ) + { + if( objects == null || objects.length == 0 ) + { return Constants.NONE; } - if (objects.length == 1) { - return this.toValue(objects[0], null); + if( objects.length == 1 ) + { + return this.toValue( objects[0], null ); } - Map result = new IdentityHashMap<>(0); + Map result = new IdentityHashMap<>( 0 ); LuaValue[] values = new LuaValue[objects.length]; - for (int i = 0; i < values.length; i++) { + for( int i = 0; i < values.length; i++ ) + { Object object = objects[i]; - values[i] = this.toValue(object, result); + values[i] = this.toValue( object, result ); } - return varargsOf(values); + return varargsOf( values ); } - private static final class HardAbortError extends Error { + private static final class HardAbortError extends Error + { static final HardAbortError INSTANCE = new HardAbortError(); private static final long serialVersionUID = 7954092008586367501L; - private HardAbortError() { - super("Hard Abort", null, true, false); + private HardAbortError() + { + super( "Hard Abort", null, true, false ); } } /** * A {@link DebugHandler} which observes the {@link TimeoutState} and responds accordingly. */ - private class TimeoutDebugHandler extends DebugHandler { + private class TimeoutDebugHandler extends DebugHandler + { private final TimeoutState timeout; boolean thrownSoftAbort; private int count = 0; @@ -481,27 +540,33 @@ public class CobaltLuaMachine implements ILuaMachine { private int oldFlags; private boolean oldInHook; - TimeoutDebugHandler() { + TimeoutDebugHandler() + { this.timeout = CobaltLuaMachine.this.timeout; } @Override - public void onInstruction(DebugState ds, DebugFrame di, int pc) throws LuaError, UnwindThrowable { + public void onInstruction( DebugState ds, DebugFrame di, int pc ) throws LuaError, UnwindThrowable + { di.pc = pc; - if (this.isPaused) { - this.resetPaused(ds, di); + if( this.isPaused ) + { + this.resetPaused( ds, di ); } // We check our current pause/abort state every 128 instructions. - if ((this.count = (this.count + 1) & 127) == 0) { + if( (this.count = (this.count + 1) & 127) == 0 ) + { // If we've been hard aborted or closed then abort. - if (this.timeout.isHardAborted() || CobaltLuaMachine.this.m_state == null) { + if( this.timeout.isHardAborted() || CobaltLuaMachine.this.m_state == null ) + { throw HardAbortError.INSTANCE; } this.timeout.refresh(); - if (this.timeout.isPaused()) { + if( this.timeout.isPaused() ) + { // Preserve the current state this.isPaused = true; this.oldInHook = ds.inhook; @@ -509,92 +574,112 @@ public class CobaltLuaMachine implements ILuaMachine { // Suspend the state. This will probably throw, but we need to handle the case where it won't. di.flags |= FLAG_HOOKYIELD | FLAG_HOOKED; - LuaThread.suspend(ds.getLuaState()); - this.resetPaused(ds, di); + LuaThread.suspend( ds.getLuaState() ); + this.resetPaused( ds, di ); } this.handleSoftAbort(); } - super.onInstruction(ds, di, pc); + super.onInstruction( ds, di, pc ); } @Override - public void poll() throws LuaError { + public void poll() throws LuaError + { // If we've been hard aborted or closed then abort. LuaState state = CobaltLuaMachine.this.m_state; - if (this.timeout.isHardAborted() || state == null) { + if( this.timeout.isHardAborted() || state == null ) + { throw HardAbortError.INSTANCE; } this.timeout.refresh(); - if (this.timeout.isPaused()) { - LuaThread.suspendBlocking(state); + if( this.timeout.isPaused() ) + { + LuaThread.suspendBlocking( state ); } this.handleSoftAbort(); } - private void resetPaused(DebugState ds, DebugFrame di) { + private void resetPaused( DebugState ds, DebugFrame di ) + { // Restore the previous paused state this.isPaused = false; ds.inhook = this.oldInHook; di.flags = this.oldFlags; } - private void handleSoftAbort() throws LuaError { + private void handleSoftAbort() throws LuaError + { // If we already thrown our soft abort error then don't do it again. - if (!this.timeout.isSoftAborted() || this.thrownSoftAbort) { + if( !this.timeout.isSoftAborted() || this.thrownSoftAbort ) + { return; } this.thrownSoftAbort = true; - throw new LuaError(TimeoutState.ABORT_MESSAGE); + throw new LuaError( TimeoutState.ABORT_MESSAGE ); } } - private class CobaltLuaContext implements ILuaContext { + private class CobaltLuaContext implements ILuaContext + { @Override - public long issueMainThreadTask(@Nonnull final ILuaTask task) throws LuaException { + public long issueMainThreadTask( @Nonnull final ILuaTask task ) throws LuaException + { // Issue command final long taskID = MainThread.getUniqueTaskID(); final Runnable iTask = () -> { - try { + try + { Object[] results = task.execute(); - if (results != null) { + if( results != null ) + { Object[] eventArguments = new Object[results.length + 2]; eventArguments[0] = taskID; eventArguments[1] = true; - System.arraycopy(results, 0, eventArguments, 2, results.length); - CobaltLuaMachine.this.m_computer.queueEvent("task_complete", eventArguments); - } else { - CobaltLuaMachine.this.m_computer.queueEvent("task_complete", - new Object[] { - taskID, - true - }); + System.arraycopy( results, 0, eventArguments, 2, results.length ); + CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", eventArguments ); } - } catch (LuaException e) { - CobaltLuaMachine.this.m_computer.queueEvent("task_complete", - new Object[] { - taskID, - false, - e.getMessage() - }); - } catch (Throwable t) { - if (ComputerCraft.logComputerErrors) { - ComputerCraft.log.error("Error running task", t); + else + { + CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", + new Object[] { + taskID, + true + } ); } - CobaltLuaMachine.this.m_computer.queueEvent("task_complete", new Object[] { + } + catch( LuaException e ) + { + CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", + new Object[] { + taskID, + false, + e.getMessage() + } ); + } + catch( Throwable t ) + { + if( ComputerCraft.logComputerErrors ) + { + ComputerCraft.log.error( "Error running task", t ); + } + CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", new Object[] { taskID, false, "Java Exception Thrown: " + t, - }); + } ); } }; - if (CobaltLuaMachine.this.m_computer.queueMainThread(iTask)) { + if( CobaltLuaMachine.this.m_computer.queueMainThread( iTask ) ) + { return taskID; - } else { - throw new LuaException("Task limit exceeded"); + } + else + { + throw new LuaException( "Task limit exceeded" ); } } } diff --git a/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java b/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java index 4008b626d..272a8d3ee 100644 --- a/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java +++ b/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java @@ -6,13 +6,12 @@ package dan200.computercraft.core.lua; -import java.io.InputStream; +import dan200.computercraft.api.lua.IDynamicLuaObject; +import dan200.computercraft.api.lua.ILuaAPI; import javax.annotation.Nonnull; import javax.annotation.Nullable; - -import dan200.computercraft.api.lua.IDynamicLuaObject; -import dan200.computercraft.api.lua.ILuaAPI; +import java.io.InputStream; /** * Represents a machine which will execute Lua code. Technically this API is flexible enough to support many languages, but you'd need a way to provide @@ -24,7 +23,8 @@ import dan200.computercraft.api.lua.ILuaAPI; * This should provide implementations of {@link dan200.computercraft.api.lua.ILuaContext}, and the ability to convert {@link IDynamicLuaObject}s into * something the VM understands, as well as handling method calls. */ -public interface ILuaMachine { +public interface ILuaMachine +{ /** * Inject an API into the global environment of this machine. This should construct an object, as it would for any {@link IDynamicLuaObject} and set it * to all names in {@link ILuaAPI#getNames()}. @@ -33,7 +33,7 @@ public interface ILuaMachine { * * @param api The API to register. */ - void addAPI(@Nonnull ILuaAPI api); + void addAPI( @Nonnull ILuaAPI api ); /** * Create a function from the provided program, and set it up to run when {@link #handleEvent(String, Object[])} is called. @@ -43,7 +43,7 @@ public interface ILuaMachine { * @param bios The stream containing the boot program. * @return The result of loading this machine. Will either be OK, or the error message when loading the bios. */ - MachineResult loadBios(@Nonnull InputStream bios); + MachineResult loadBios( @Nonnull InputStream bios ); /** * Resume the machine, either starting or resuming the coroutine. @@ -51,11 +51,11 @@ public interface ILuaMachine { * This should destroy the machine if it failed to execute successfully. * * @param eventName The name of the event. This is {@code null} when first starting the machine. Note, this may do nothing if it does not match the - * event filter. + * event filter. * @param arguments The arguments for this event. * @return The result of loading this machine. Will either be OK, or the error message that occurred when executing. */ - MachineResult handleEvent(@Nullable String eventName, @Nullable Object[] arguments); + MachineResult handleEvent( @Nullable String eventName, @Nullable Object[] arguments ); /** * Close the Lua machine, aborting any running functions and deleting the internal state. diff --git a/src/main/java/dan200/computercraft/core/lua/MachineResult.java b/src/main/java/dan200/computercraft/core/lua/MachineResult.java index 5e947abab..f5cc1058b 100644 --- a/src/main/java/dan200/computercraft/core/lua/MachineResult.java +++ b/src/main/java/dan200/computercraft/core/lua/MachineResult.java @@ -6,12 +6,11 @@ package dan200.computercraft.core.lua; -import java.io.InputStream; +import dan200.computercraft.core.computer.TimeoutState; import javax.annotation.Nonnull; import javax.annotation.Nullable; - -import dan200.computercraft.core.computer.TimeoutState; +import java.io.InputStream; /** * The result of executing an action on a machine. @@ -21,55 +20,62 @@ import dan200.computercraft.core.computer.TimeoutState; * @see ILuaMachine#loadBios(InputStream) * @see ILuaMachine#handleEvent(String, Object[]) */ -public final class MachineResult { +public final class MachineResult +{ /** * A successful complete execution. */ - public static final MachineResult OK = new MachineResult(false, false, null); + public static final MachineResult OK = new MachineResult( false, false, null ); /** * A successful paused execution. */ - public static final MachineResult PAUSE = new MachineResult(false, true, null); + public static final MachineResult PAUSE = new MachineResult( false, true, null ); /** * An execution which timed out. */ - public static final MachineResult TIMEOUT = new MachineResult(true, false, TimeoutState.ABORT_MESSAGE); + public static final MachineResult TIMEOUT = new MachineResult( true, false, TimeoutState.ABORT_MESSAGE ); /** * An error with no user-friendly error message. */ - public static final MachineResult GENERIC_ERROR = new MachineResult(true, false, null); + public static final MachineResult GENERIC_ERROR = new MachineResult( true, false, null ); private final boolean error; private final boolean pause; private final String message; - private MachineResult(boolean error, boolean pause, String message) { + private MachineResult( boolean error, boolean pause, String message ) + { this.pause = pause; this.message = message; this.error = error; } - public static MachineResult error(@Nonnull String error) { - return new MachineResult(true, false, error); + public static MachineResult error( @Nonnull String error ) + { + return new MachineResult( true, false, error ); } - public static MachineResult error(@Nonnull Exception error) { - return new MachineResult(true, false, error.getMessage()); + public static MachineResult error( @Nonnull Exception error ) + { + return new MachineResult( true, false, error.getMessage() ); } - public boolean isError() { + public boolean isError() + { return this.error; } - public boolean isPause() { + public boolean isPause() + { return this.pause; } @Nullable - public String getMessage() { + public String getMessage() + { return this.message; } } diff --git a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java index 12aacf219..90b6bd70b 100644 --- a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java @@ -5,34 +5,29 @@ */ package dan200.computercraft.core.lua; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaCallback; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.lua.*; import dan200.computercraft.core.asm.LuaMethod; -import org.squiddev.cobalt.LuaError; -import org.squiddev.cobalt.LuaState; -import org.squiddev.cobalt.LuaThread; -import org.squiddev.cobalt.UnwindThrowable; -import org.squiddev.cobalt.Varargs; +import org.squiddev.cobalt.*; import org.squiddev.cobalt.debug.DebugFrame; import org.squiddev.cobalt.function.ResumableVarArgFunction; +import javax.annotation.Nonnull; + /** * Calls a {@link LuaMethod}, and interprets the resulting {@link MethodResult}, either returning the result or yielding and resuming the supplied * continuation. */ -class ResultInterpreterFunction extends ResumableVarArgFunction { +class ResultInterpreterFunction extends ResumableVarArgFunction +{ private final CobaltLuaMachine machine; private final LuaMethod method; private final Object instance; private final ILuaContext context; private final String name; - ResultInterpreterFunction(CobaltLuaMachine machine, LuaMethod method, Object instance, ILuaContext context, String name) { + + ResultInterpreterFunction( CobaltLuaMachine machine, LuaMethod method, Object instance, ILuaContext context, String name ) + { this.machine = machine; this.method = method; this.instance = instance; @@ -41,72 +36,92 @@ class ResultInterpreterFunction extends ResumableVarArgFunction= this.varargs.count()) { + public Object get( int index ) + { + if( index < 0 || index >= this.varargs.count() ) + { return null; } Object[] cache = this.cache; - if (cache == null) { + if( cache == null ) + { cache = this.cache = new Object[this.varargs.count()]; - } else { + } + else + { Object existing = cache[index]; - if (existing != null) { + if( existing != null ) + { return existing; } } - return cache[index] = CobaltLuaMachine.toObject(this.varargs.arg(index + 1), null); + return cache[index] = CobaltLuaMachine.toObject( this.varargs.arg( index + 1 ), null ); } @Override - public long getLong(int index) throws LuaException { - LuaValue value = this.varargs.arg(index + 1); - if (!(value instanceof LuaNumber)) { - throw LuaValues.badArgument(index, "number", value.typeName()); + public long getLong( int index ) throws LuaException + { + LuaValue value = this.varargs.arg( index + 1 ); + if( !(value instanceof LuaNumber) ) + { + throw LuaValues.badArgument( index, "number", value.typeName() ); } - return value instanceof LuaInteger ? value.toInteger() : (long) LuaValues.checkFinite(index, value.toDouble()); + return value instanceof LuaInteger ? value.toInteger() : (long) LuaValues.checkFinite( index, value.toDouble() ); } @Override - public double getDouble(int index) throws LuaException { - LuaValue value = this.varargs.arg(index + 1); - if (!(value instanceof LuaNumber)) { - throw LuaValues.badArgument(index, "number", value.typeName()); + public double getDouble( int index ) throws LuaException + { + LuaValue value = this.varargs.arg( index + 1 ); + if( !(value instanceof LuaNumber) ) + { + throw LuaValues.badArgument( index, "number", value.typeName() ); } return value.toDouble(); } @Nonnull @Override - public ByteBuffer getBytes(int index) throws LuaException { - LuaValue value = this.varargs.arg(index + 1); - if (!(value instanceof LuaBaseString)) { - throw LuaValues.badArgument(index, "string", value.typeName()); + public ByteBuffer getBytes( int index ) throws LuaException + { + LuaValue value = this.varargs.arg( index + 1 ); + if( !(value instanceof LuaBaseString) ) + { + throw LuaValues.badArgument( index, "string", value.typeName() ); } LuaString str = ((LuaBaseString) value).strvalue(); - return ByteBuffer.wrap(str.bytes, str.offset, str.length) - .asReadOnlyBuffer(); + return ByteBuffer.wrap( str.bytes, str.offset, str.length ) + .asReadOnlyBuffer(); } @Override - public Optional optBytes(int index) throws LuaException { - LuaValue value = this.varargs.arg(index + 1); - if (value.isNil()) { + public Optional optBytes( int index ) throws LuaException + { + LuaValue value = this.varargs.arg( index + 1 ); + if( value.isNil() ) + { return Optional.empty(); } - if (!(value instanceof LuaBaseString)) { - throw LuaValues.badArgument(index, "string", value.typeName()); + if( !(value instanceof LuaBaseString) ) + { + throw LuaValues.badArgument( index, "string", value.typeName() ); } LuaString str = ((LuaBaseString) value).strvalue(); - return Optional.of(ByteBuffer.wrap(str.bytes, str.offset, str.length) - .asReadOnlyBuffer()); + return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ) + .asReadOnlyBuffer() ); } } diff --git a/src/main/java/dan200/computercraft/core/terminal/Terminal.java b/src/main/java/dan200/computercraft/core/terminal/Terminal.java index 8fcc07c6f..08fe1d01f 100644 --- a/src/main/java/dan200/computercraft/core/terminal/Terminal.java +++ b/src/main/java/dan200/computercraft/core/terminal/Terminal.java @@ -6,15 +6,15 @@ package dan200.computercraft.core.terminal; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; - import net.minecraft.nbt.CompoundTag; import net.minecraft.network.PacketByteBuf; -public class Terminal { +import javax.annotation.Nonnull; + +public class Terminal +{ private static final String base16 = "0123456789abcdef"; private final Palette m_palette = new Palette(); private final Runnable onChanged; @@ -29,11 +29,13 @@ public class Terminal { private TextBuffer[] m_textColour; private TextBuffer[] m_backgroundColour; - public Terminal(int width, int height) { - this(width, height, null); + public Terminal( int width, int height ) + { + this( width, height, null ); } - public Terminal(int width, int height, Runnable changedCallback) { + public Terminal( int width, int height, Runnable changedCallback ) + { this.m_width = width; this.m_height = height; this.onChanged = changedCallback; @@ -41,14 +43,16 @@ public class Terminal { this.m_text = new TextBuffer[this.m_height]; this.m_textColour = new TextBuffer[this.m_height]; this.m_backgroundColour = new TextBuffer[this.m_height]; - for (int i = 0; i < this.m_height; i++) { - this.m_text[i] = new TextBuffer(' ', this.m_width); - this.m_textColour[i] = new TextBuffer(base16.charAt(this.m_cursorColour), this.m_width); - this.m_backgroundColour[i] = new TextBuffer(base16.charAt(this.m_cursorBackgroundColour), this.m_width); + for( int i = 0; i < this.m_height; i++ ) + { + this.m_text[i] = new TextBuffer( ' ', this.m_width ); + this.m_textColour[i] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); + this.m_backgroundColour[i] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); } } - public synchronized void reset() { + public synchronized void reset() + { this.m_cursorColour = 0; this.m_cursorBackgroundColour = 15; this.m_cursorX = 0; @@ -59,31 +63,39 @@ public class Terminal { this.m_palette.resetColours(); } - public synchronized void clear() { - for (int y = 0; y < this.m_height; y++) { - this.m_text[y].fill(' '); - this.m_textColour[y].fill(base16.charAt(this.m_cursorColour)); - this.m_backgroundColour[y].fill(base16.charAt(this.m_cursorBackgroundColour)); + public synchronized void clear() + { + for( int y = 0; y < this.m_height; y++ ) + { + this.m_text[y].fill( ' ' ); + this.m_textColour[y].fill( base16.charAt( this.m_cursorColour ) ); + this.m_backgroundColour[y].fill( base16.charAt( this.m_cursorBackgroundColour ) ); } this.setChanged(); } - public final void setChanged() { - if (this.onChanged != null) { + public final void setChanged() + { + if( this.onChanged != null ) + { this.onChanged.run(); } } - public int getWidth() { + public int getWidth() + { return this.m_width; } - public int getHeight() { + public int getHeight() + { return this.m_height; } - public synchronized void resize(int width, int height) { - if (width == this.m_width && height == this.m_height) { + public synchronized void resize( int width, int height ) + { + if( width == this.m_width && height == this.m_height ) + { return; } @@ -99,118 +111,148 @@ public class Terminal { this.m_text = new TextBuffer[this.m_height]; this.m_textColour = new TextBuffer[this.m_height]; this.m_backgroundColour = new TextBuffer[this.m_height]; - for (int i = 0; i < this.m_height; i++) { - if (i >= oldHeight) { - this.m_text[i] = new TextBuffer(' ', this.m_width); - this.m_textColour[i] = new TextBuffer(base16.charAt(this.m_cursorColour), this.m_width); - this.m_backgroundColour[i] = new TextBuffer(base16.charAt(this.m_cursorBackgroundColour), this.m_width); - } else if (this.m_width == oldWidth) { + for( int i = 0; i < this.m_height; i++ ) + { + if( i >= oldHeight ) + { + this.m_text[i] = new TextBuffer( ' ', this.m_width ); + this.m_textColour[i] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); + this.m_backgroundColour[i] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); + } + else if( this.m_width == oldWidth ) + { this.m_text[i] = oldText[i]; this.m_textColour[i] = oldTextColour[i]; this.m_backgroundColour[i] = oldBackgroundColour[i]; - } else { - this.m_text[i] = new TextBuffer(' ', this.m_width); - this.m_textColour[i] = new TextBuffer(base16.charAt(this.m_cursorColour), this.m_width); - this.m_backgroundColour[i] = new TextBuffer(base16.charAt(this.m_cursorBackgroundColour), this.m_width); - this.m_text[i].write(oldText[i]); - this.m_textColour[i].write(oldTextColour[i]); - this.m_backgroundColour[i].write(oldBackgroundColour[i]); + } + else + { + this.m_text[i] = new TextBuffer( ' ', this.m_width ); + this.m_textColour[i] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); + this.m_backgroundColour[i] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); + this.m_text[i].write( oldText[i] ); + this.m_textColour[i].write( oldTextColour[i] ); + this.m_backgroundColour[i].write( oldBackgroundColour[i] ); } } this.setChanged(); } - public void setCursorPos(int x, int y) { - if (this.m_cursorX != x || this.m_cursorY != y) { + public void setCursorPos( int x, int y ) + { + if( this.m_cursorX != x || this.m_cursorY != y ) + { this.m_cursorX = x; this.m_cursorY = y; this.setChanged(); } } - public int getCursorX() { + public int getCursorX() + { return this.m_cursorX; } - public int getCursorY() { + public int getCursorY() + { return this.m_cursorY; } - public boolean getCursorBlink() { + public boolean getCursorBlink() + { return this.m_cursorBlink; } - public void setCursorBlink(boolean blink) { - if (this.m_cursorBlink != blink) { + public void setCursorBlink( boolean blink ) + { + if( this.m_cursorBlink != blink ) + { this.m_cursorBlink = blink; this.setChanged(); } } - public int getTextColour() { + public int getTextColour() + { return this.m_cursorColour; } - public void setTextColour(int colour) { - if (this.m_cursorColour != colour) { + public void setTextColour( int colour ) + { + if( this.m_cursorColour != colour ) + { this.m_cursorColour = colour; this.setChanged(); } } - public int getBackgroundColour() { + public int getBackgroundColour() + { return this.m_cursorBackgroundColour; } - public void setBackgroundColour(int colour) { - if (this.m_cursorBackgroundColour != colour) { + public void setBackgroundColour( int colour ) + { + if( this.m_cursorBackgroundColour != colour ) + { this.m_cursorBackgroundColour = colour; this.setChanged(); } } @Nonnull - public Palette getPalette() { + public Palette getPalette() + { return this.m_palette; } - public synchronized void blit(String text, String textColour, String backgroundColour) { + public synchronized void blit( String text, String textColour, String backgroundColour ) + { int x = this.m_cursorX; int y = this.m_cursorY; - if (y >= 0 && y < this.m_height) { - this.m_text[y].write(text, x); - this.m_textColour[y].write(textColour, x); - this.m_backgroundColour[y].write(backgroundColour, x); + if( y >= 0 && y < this.m_height ) + { + this.m_text[y].write( text, x ); + this.m_textColour[y].write( textColour, x ); + this.m_backgroundColour[y].write( backgroundColour, x ); this.setChanged(); } } - public synchronized void write(String text) { + public synchronized void write( String text ) + { int x = this.m_cursorX; int y = this.m_cursorY; - if (y >= 0 && y < this.m_height) { - this.m_text[y].write(text, x); - this.m_textColour[y].fill(base16.charAt(this.m_cursorColour), x, x + text.length()); - this.m_backgroundColour[y].fill(base16.charAt(this.m_cursorBackgroundColour), x, x + text.length()); + if( y >= 0 && y < this.m_height ) + { + this.m_text[y].write( text, x ); + this.m_textColour[y].fill( base16.charAt( this.m_cursorColour ), x, x + text.length() ); + this.m_backgroundColour[y].fill( base16.charAt( this.m_cursorBackgroundColour ), x, x + text.length() ); this.setChanged(); } } - public synchronized void scroll(int yDiff) { - if (yDiff != 0) { + public synchronized void scroll( int yDiff ) + { + if( yDiff != 0 ) + { TextBuffer[] newText = new TextBuffer[this.m_height]; TextBuffer[] newTextColour = new TextBuffer[this.m_height]; TextBuffer[] newBackgroundColour = new TextBuffer[this.m_height]; - for (int y = 0; y < this.m_height; y++) { + for( int y = 0; y < this.m_height; y++ ) + { int oldY = y + yDiff; - if (oldY >= 0 && oldY < this.m_height) { + if( oldY >= 0 && oldY < this.m_height ) + { newText[y] = this.m_text[oldY]; newTextColour[y] = this.m_textColour[oldY]; newBackgroundColour[y] = this.m_backgroundColour[oldY]; - } else { - newText[y] = new TextBuffer(' ', this.m_width); - newTextColour[y] = new TextBuffer(base16.charAt(this.m_cursorColour), this.m_width); - newBackgroundColour[y] = new TextBuffer(base16.charAt(this.m_cursorBackgroundColour), this.m_width); + } + else + { + newText[y] = new TextBuffer( ' ', this.m_width ); + newTextColour[y] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); + newBackgroundColour[y] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); } } this.m_text = newText; @@ -220,75 +262,91 @@ public class Terminal { } } - public synchronized void clearLine() { + public synchronized void clearLine() + { int y = this.m_cursorY; - if (y >= 0 && y < this.m_height) { - this.m_text[y].fill(' '); - this.m_textColour[y].fill(base16.charAt(this.m_cursorColour)); - this.m_backgroundColour[y].fill(base16.charAt(this.m_cursorBackgroundColour)); + if( y >= 0 && y < this.m_height ) + { + this.m_text[y].fill( ' ' ); + this.m_textColour[y].fill( base16.charAt( this.m_cursorColour ) ); + this.m_backgroundColour[y].fill( base16.charAt( this.m_cursorBackgroundColour ) ); this.setChanged(); } } - public synchronized TextBuffer getLine(int y) { - if (y >= 0 && y < this.m_height) { + public synchronized TextBuffer getLine( int y ) + { + if( y >= 0 && y < this.m_height ) + { return this.m_text[y]; } return null; } - public synchronized void setLine(int y, String text, String textColour, String backgroundColour) { - this.m_text[y].write(text); - this.m_textColour[y].write(textColour); - this.m_backgroundColour[y].write(backgroundColour); + public synchronized void setLine( int y, String text, String textColour, String backgroundColour ) + { + this.m_text[y].write( text ); + this.m_textColour[y].write( textColour ); + this.m_backgroundColour[y].write( backgroundColour ); this.setChanged(); } - public synchronized TextBuffer getTextColourLine(int y) { - if (y >= 0 && y < this.m_height) { + public synchronized TextBuffer getTextColourLine( int y ) + { + if( y >= 0 && y < this.m_height ) + { return this.m_textColour[y]; } return null; } - public synchronized TextBuffer getBackgroundColourLine(int y) { - if (y >= 0 && y < this.m_height) { + public synchronized TextBuffer getBackgroundColourLine( int y ) + { + if( y >= 0 && y < this.m_height ) + { return this.m_backgroundColour[y]; } return null; } - public synchronized void write(PacketByteBuf buffer) { - buffer.writeInt(this.m_cursorX); - buffer.writeInt(this.m_cursorY); - buffer.writeBoolean(this.m_cursorBlink); - buffer.writeByte(this.m_cursorBackgroundColour << 4 | this.m_cursorColour); + public synchronized void write( PacketByteBuf buffer ) + { + buffer.writeInt( this.m_cursorX ); + buffer.writeInt( this.m_cursorY ); + buffer.writeBoolean( this.m_cursorBlink ); + buffer.writeByte( this.m_cursorBackgroundColour << 4 | this.m_cursorColour ); - for (int y = 0; y < this.m_height; y++) { + for( int y = 0; y < this.m_height; y++ ) + { TextBuffer text = this.m_text[y]; TextBuffer textColour = this.m_textColour[y]; TextBuffer backColour = this.m_backgroundColour[y]; - for (int x = 0; x < this.m_width; x++) { - buffer.writeByte(text.charAt(x) & 0xFF); - buffer.writeByte(getColour(backColour.charAt(x), Colour.BLACK) << 4 | getColour(textColour.charAt(x), Colour.WHITE)); + for( int x = 0; x < this.m_width; x++ ) + { + buffer.writeByte( text.charAt( x ) & 0xFF ); + buffer.writeByte( getColour( backColour.charAt( x ), Colour.BLACK ) << 4 | getColour( textColour.charAt( x ), Colour.WHITE ) ); } } - this.m_palette.write(buffer); + this.m_palette.write( buffer ); } - public static int getColour(char c, Colour def) { - if (c >= '0' && c <= '9') { + public static int getColour( char c, Colour def ) + { + if( c >= '0' && c <= '9' ) + { return c - '0'; } - if (c >= 'a' && c <= 'f') { + if( c >= 'a' && c <= 'f' ) + { return c - 'a' + 10; } return 15 - def.ordinal(); } - public synchronized void read(PacketByteBuf buffer) { + public synchronized void read( PacketByteBuf buffer ) + { this.m_cursorX = buffer.readInt(); this.m_cursorY = buffer.readInt(); this.m_cursorBlink = buffer.readBoolean(); @@ -297,63 +355,72 @@ public class Terminal { this.m_cursorBackgroundColour = (cursorColour >> 4) & 0xF; this.m_cursorColour = cursorColour & 0xF; - for (int y = 0; y < this.m_height; y++) { + for( int y = 0; y < this.m_height; y++ ) + { TextBuffer text = this.m_text[y]; TextBuffer textColour = this.m_textColour[y]; TextBuffer backColour = this.m_backgroundColour[y]; - for (int x = 0; x < this.m_width; x++) { - text.setChar(x, (char) (buffer.readByte() & 0xFF)); + for( int x = 0; x < this.m_width; x++ ) + { + text.setChar( x, (char) (buffer.readByte() & 0xFF) ); byte colour = buffer.readByte(); - backColour.setChar(x, base16.charAt((colour >> 4) & 0xF)); - textColour.setChar(x, base16.charAt(colour & 0xF)); + backColour.setChar( x, base16.charAt( (colour >> 4) & 0xF ) ); + textColour.setChar( x, base16.charAt( colour & 0xF ) ); } } - this.m_palette.read(buffer); + this.m_palette.read( buffer ); this.setChanged(); } - public synchronized CompoundTag writeToNBT(CompoundTag nbt) { - nbt.putInt("term_cursorX", this.m_cursorX); - nbt.putInt("term_cursorY", this.m_cursorY); - nbt.putBoolean("term_cursorBlink", this.m_cursorBlink); - nbt.putInt("term_textColour", this.m_cursorColour); - nbt.putInt("term_bgColour", this.m_cursorBackgroundColour); - for (int n = 0; n < this.m_height; n++) { - nbt.putString("term_text_" + n, this.m_text[n].toString()); - nbt.putString("term_textColour_" + n, this.m_textColour[n].toString()); - nbt.putString("term_textBgColour_" + n, this.m_backgroundColour[n].toString()); + public synchronized CompoundTag writeToNBT( CompoundTag nbt ) + { + nbt.putInt( "term_cursorX", this.m_cursorX ); + nbt.putInt( "term_cursorY", this.m_cursorY ); + nbt.putBoolean( "term_cursorBlink", this.m_cursorBlink ); + nbt.putInt( "term_textColour", this.m_cursorColour ); + nbt.putInt( "term_bgColour", this.m_cursorBackgroundColour ); + for( int n = 0; n < this.m_height; n++ ) + { + nbt.putString( "term_text_" + n, this.m_text[n].toString() ); + nbt.putString( "term_textColour_" + n, this.m_textColour[n].toString() ); + nbt.putString( "term_textBgColour_" + n, this.m_backgroundColour[n].toString() ); } - this.m_palette.writeToNBT(nbt); + this.m_palette.writeToNBT( nbt ); return nbt; } - public synchronized void readFromNBT(CompoundTag nbt) { - this.m_cursorX = nbt.getInt("term_cursorX"); - this.m_cursorY = nbt.getInt("term_cursorY"); - this.m_cursorBlink = nbt.getBoolean("term_cursorBlink"); - this.m_cursorColour = nbt.getInt("term_textColour"); - this.m_cursorBackgroundColour = nbt.getInt("term_bgColour"); + public synchronized void readFromNBT( CompoundTag nbt ) + { + this.m_cursorX = nbt.getInt( "term_cursorX" ); + this.m_cursorY = nbt.getInt( "term_cursorY" ); + this.m_cursorBlink = nbt.getBoolean( "term_cursorBlink" ); + this.m_cursorColour = nbt.getInt( "term_textColour" ); + this.m_cursorBackgroundColour = nbt.getInt( "term_bgColour" ); - for (int n = 0; n < this.m_height; n++) { - this.m_text[n].fill(' '); - if (nbt.contains("term_text_" + n)) { - this.m_text[n].write(nbt.getString("term_text_" + n)); + for( int n = 0; n < this.m_height; n++ ) + { + this.m_text[n].fill( ' ' ); + if( nbt.contains( "term_text_" + n ) ) + { + this.m_text[n].write( nbt.getString( "term_text_" + n ) ); } - this.m_textColour[n].fill(base16.charAt(this.m_cursorColour)); - if (nbt.contains("term_textColour_" + n)) { - this.m_textColour[n].write(nbt.getString("term_textColour_" + n)); + this.m_textColour[n].fill( base16.charAt( this.m_cursorColour ) ); + if( nbt.contains( "term_textColour_" + n ) ) + { + this.m_textColour[n].write( nbt.getString( "term_textColour_" + n ) ); } - this.m_backgroundColour[n].fill(base16.charAt(this.m_cursorBackgroundColour)); - if (nbt.contains("term_textBgColour_" + n)) { - this.m_backgroundColour[n].write(nbt.getString("term_textBgColour_" + n)); + this.m_backgroundColour[n].fill( base16.charAt( this.m_cursorBackgroundColour ) ); + if( nbt.contains( "term_textBgColour_" + n ) ) + { + this.m_backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) ); } } - this.m_palette.readFromNBT(nbt); + this.m_palette.readFromNBT( nbt ); this.setChanged(); } } diff --git a/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java b/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java index 7979b8777..0fbb848a2 100644 --- a/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java +++ b/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java @@ -6,14 +6,14 @@ package dan200.computercraft.core.tracking; -import java.lang.ref.WeakReference; - -import javax.annotation.Nullable; - import dan200.computercraft.core.computer.Computer; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -public class ComputerTracker { +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; + +public class ComputerTracker +{ private final WeakReference computer; private final int computerId; private final Object2LongOpenHashMap fields; @@ -23,13 +23,15 @@ public class ComputerTracker { private long serverCount; private long serverTime; - public ComputerTracker(Computer computer) { - this.computer = new WeakReference<>(computer); + public ComputerTracker( Computer computer ) + { + this.computer = new WeakReference<>( computer ); this.computerId = computer.getID(); this.fields = new Object2LongOpenHashMap<>(); } - ComputerTracker(ComputerTracker timings) { + ComputerTracker( ComputerTracker timings ) + { this.computer = timings.computer; this.computerId = timings.computerId; @@ -40,80 +42,100 @@ public class ComputerTracker { this.serverCount = timings.serverCount; this.serverTime = timings.serverTime; - this.fields = new Object2LongOpenHashMap<>(timings.fields); + this.fields = new Object2LongOpenHashMap<>( timings.fields ); } @Nullable - public Computer getComputer() { + public Computer getComputer() + { return this.computer.get(); } - public int getComputerId() { + public int getComputerId() + { return this.computerId; } - public long getTasks() { + public long getTasks() + { return this.tasks; } - public long getTotalTime() { + public long getTotalTime() + { return this.totalTime; } - public long getMaxTime() { + public long getMaxTime() + { return this.maxTime; } - public long getAverage() { + public long getAverage() + { return this.totalTime / this.tasks; } - void addTaskTiming(long time) { + void addTaskTiming( long time ) + { this.tasks++; this.totalTime += time; - if (time > this.maxTime) { + if( time > this.maxTime ) + { this.maxTime = time; } } - void addMainTiming(long time) { + void addMainTiming( long time ) + { this.serverCount++; this.serverTime += time; } - void addValue(TrackingField field, long change) { - synchronized (this.fields) { - this.fields.addTo(field, change); + void addValue( TrackingField field, long change ) + { + synchronized( this.fields ) + { + this.fields.addTo( field, change ); } } - public String getFormatted(TrackingField field) { - return field.format(this.get(field)); + public String getFormatted( TrackingField field ) + { + return field.format( this.get( field ) ); } - public long get(TrackingField field) { - if (field == TrackingField.TASKS) { + public long get( TrackingField field ) + { + if( field == TrackingField.TASKS ) + { return this.tasks; } - if (field == TrackingField.MAX_TIME) { + if( field == TrackingField.MAX_TIME ) + { return this.maxTime; } - if (field == TrackingField.TOTAL_TIME) { + if( field == TrackingField.TOTAL_TIME ) + { return this.totalTime; } - if (field == TrackingField.AVERAGE_TIME) { + if( field == TrackingField.AVERAGE_TIME ) + { return this.tasks == 0 ? 0 : this.totalTime / this.tasks; } - if (field == TrackingField.SERVER_COUNT) { + if( field == TrackingField.SERVER_COUNT ) + { return this.serverCount; } - if (field == TrackingField.SERVER_TIME) { + if( field == TrackingField.SERVER_TIME ) + { return this.serverTime; } - synchronized (this.fields) { - return this.fields.getLong(field); + synchronized( this.fields ) + { + return this.fields.getLong( field ); } } } diff --git a/src/main/java/dan200/computercraft/core/tracking/Tracker.java b/src/main/java/dan200/computercraft/core/tracking/Tracker.java index 7daf006af..fd9220c9e 100644 --- a/src/main/java/dan200/computercraft/core/tracking/Tracker.java +++ b/src/main/java/dan200/computercraft/core/tracking/Tracker.java @@ -8,16 +8,18 @@ package dan200.computercraft.core.tracking; import dan200.computercraft.core.computer.Computer; -public interface Tracker { +public interface Tracker +{ /** * Report how long a task executed on the computer thread took. * * Computer thread tasks include events or a computer being turned on/off. * * @param computer The computer processing this task - * @param time The time taken for this task. + * @param time The time taken for this task. */ - default void addTaskTiming(Computer computer, long time) { + default void addTaskTiming( Computer computer, long time ) + { } /** @@ -26,9 +28,10 @@ public interface Tracker { * Server tasks include actions performed by peripherals. * * @param computer The computer processing this task - * @param time The time taken for this task. + * @param time The time taken for this task. */ - default void addServerTiming(Computer computer, long time) { + default void addServerTiming( Computer computer, long time ) + { } /** @@ -36,9 +39,10 @@ public interface Tracker { * "average". * * @param computer The computer to increment - * @param field The field to increment. - * @param change The amount to increment said field by. + * @param field The field to increment. + * @param change The amount to increment said field by. */ - default void addValue(Computer computer, TrackingField field, long change) { + default void addValue( Computer computer, TrackingField field, long change ) + { } } diff --git a/src/main/java/dan200/computercraft/core/tracking/Tracking.java b/src/main/java/dan200/computercraft/core/tracking/Tracking.java index 34e826900..01347f294 100644 --- a/src/main/java/dan200/computercraft/core/tracking/Tracking.java +++ b/src/main/java/dan200/computercraft/core/tracking/Tracking.java @@ -6,16 +6,17 @@ package dan200.computercraft.core.tracking; +import dan200.computercraft.core.computer.Computer; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; -import dan200.computercraft.core.computer.Computer; - -public final class Tracking { - static final AtomicInteger tracking = new AtomicInteger(0); +public final class Tracking +{ + static final AtomicInteger tracking = new AtomicInteger( 0 ); private static final Object lock = new Object(); private static final HashMap contexts = new HashMap<>(); @@ -23,73 +24,95 @@ public final class Tracking { private Tracking() {} - public static TrackingContext getContext(UUID uuid) { - synchronized (lock) { - TrackingContext context = contexts.get(uuid); - if (context == null) { - contexts.put(uuid, context = new TrackingContext()); + public static TrackingContext getContext( UUID uuid ) + { + synchronized( lock ) + { + TrackingContext context = contexts.get( uuid ); + if( context == null ) + { + contexts.put( uuid, context = new TrackingContext() ); } return context; } } - public static void add(Tracker tracker) { - synchronized (lock) { - trackers.add(tracker); + public static void add( Tracker tracker ) + { + synchronized( lock ) + { + trackers.add( tracker ); tracking.incrementAndGet(); } } - public static void addTaskTiming(Computer computer, long time) { - if (tracking.get() == 0) { + public static void addTaskTiming( Computer computer, long time ) + { + if( tracking.get() == 0 ) + { return; } - synchronized (contexts) { - for (TrackingContext context : contexts.values()) { - context.addTaskTiming(computer, time); + synchronized( contexts ) + { + for( TrackingContext context : contexts.values() ) + { + context.addTaskTiming( computer, time ); } - for (Tracker tracker : trackers) { - tracker.addTaskTiming(computer, time); + for( Tracker tracker : trackers ) + { + tracker.addTaskTiming( computer, time ); } } } - public static void addServerTiming(Computer computer, long time) { - if (tracking.get() == 0) { + public static void addServerTiming( Computer computer, long time ) + { + if( tracking.get() == 0 ) + { return; } - synchronized (contexts) { - for (TrackingContext context : contexts.values()) { - context.addServerTiming(computer, time); + synchronized( contexts ) + { + for( TrackingContext context : contexts.values() ) + { + context.addServerTiming( computer, time ); } - for (Tracker tracker : trackers) { - tracker.addServerTiming(computer, time); + for( Tracker tracker : trackers ) + { + tracker.addServerTiming( computer, time ); } } } - public static void addValue(Computer computer, TrackingField field, long change) { - if (tracking.get() == 0) { + public static void addValue( Computer computer, TrackingField field, long change ) + { + if( tracking.get() == 0 ) + { return; } - synchronized (lock) { - for (TrackingContext context : contexts.values()) { - context.addValue(computer, field, change); + synchronized( lock ) + { + for( TrackingContext context : contexts.values() ) + { + context.addValue( computer, field, change ); } - for (Tracker tracker : trackers) { - tracker.addValue(computer, field, change); + for( Tracker tracker : trackers ) + { + tracker.addValue( computer, field, change ); } } } - public static void reset() { - synchronized (lock) { + public static void reset() + { + synchronized( lock ) + { contexts.clear(); trackers.clear(); - tracking.set(0); + tracking.set( 0 ); } } } diff --git a/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java b/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java index b8bcfb81a..24d448061 100644 --- a/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java +++ b/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java @@ -6,26 +6,29 @@ package dan200.computercraft.core.tracking; +import com.google.common.collect.MapMaker; +import dan200.computercraft.core.computer.Computer; + import java.util.ArrayList; import java.util.List; import java.util.Map; -import com.google.common.collect.MapMaker; -import dan200.computercraft.core.computer.Computer; - /** * Tracks timing information about computers, including how long they ran for and the number of events they handled. * * Note that this will track computers which have been deleted (hence the presence of {@link #timingLookup} and {@link #timings} */ -public class TrackingContext implements Tracker { +public class TrackingContext implements Tracker +{ private final List timings = new ArrayList<>(); private final Map timingLookup = new MapMaker().weakKeys() - .makeMap(); + .makeMap(); private boolean tracking = false; - public synchronized void start() { - if (!this.tracking) { + public synchronized void start() + { + if( !this.tracking ) + { Tracking.tracking.incrementAndGet(); } this.tracking = true; @@ -34,8 +37,10 @@ public class TrackingContext implements Tracker { this.timingLookup.clear(); } - public synchronized boolean stop() { - if (!this.tracking) { + public synchronized boolean stop() + { + if( !this.tracking ) + { return false; } @@ -45,69 +50,84 @@ public class TrackingContext implements Tracker { return true; } - public synchronized List getImmutableTimings() { - ArrayList timings = new ArrayList<>(this.timings.size()); - for (ComputerTracker timing : this.timings) { - timings.add(new ComputerTracker(timing)); + public synchronized List getImmutableTimings() + { + ArrayList timings = new ArrayList<>( this.timings.size() ); + for( ComputerTracker timing : this.timings ) + { + timings.add( new ComputerTracker( timing ) ); } return timings; } - public synchronized List getTimings() { - return new ArrayList<>(this.timings); + public synchronized List getTimings() + { + return new ArrayList<>( this.timings ); } @Override - public void addTaskTiming(Computer computer, long time) { - if (!this.tracking) { + public void addTaskTiming( Computer computer, long time ) + { + if( !this.tracking ) + { return; } - synchronized (this) { - ComputerTracker computerTimings = this.timingLookup.get(computer); - if (computerTimings == null) { - computerTimings = new ComputerTracker(computer); - this.timingLookup.put(computer, computerTimings); - this.timings.add(computerTimings); + synchronized( this ) + { + ComputerTracker computerTimings = this.timingLookup.get( computer ); + if( computerTimings == null ) + { + computerTimings = new ComputerTracker( computer ); + this.timingLookup.put( computer, computerTimings ); + this.timings.add( computerTimings ); } - computerTimings.addTaskTiming(time); + computerTimings.addTaskTiming( time ); } } @Override - public void addServerTiming(Computer computer, long time) { - if (!this.tracking) { + public void addServerTiming( Computer computer, long time ) + { + if( !this.tracking ) + { return; } - synchronized (this) { - ComputerTracker computerTimings = this.timingLookup.get(computer); - if (computerTimings == null) { - computerTimings = new ComputerTracker(computer); - this.timingLookup.put(computer, computerTimings); - this.timings.add(computerTimings); + synchronized( this ) + { + ComputerTracker computerTimings = this.timingLookup.get( computer ); + if( computerTimings == null ) + { + computerTimings = new ComputerTracker( computer ); + this.timingLookup.put( computer, computerTimings ); + this.timings.add( computerTimings ); } - computerTimings.addMainTiming(time); + computerTimings.addMainTiming( time ); } } @Override - public void addValue(Computer computer, TrackingField field, long change) { - if (!this.tracking) { + public void addValue( Computer computer, TrackingField field, long change ) + { + if( !this.tracking ) + { return; } - synchronized (this) { - ComputerTracker computerTimings = this.timingLookup.get(computer); - if (computerTimings == null) { - computerTimings = new ComputerTracker(computer); - this.timingLookup.put(computer, computerTimings); - this.timings.add(computerTimings); + synchronized( this ) + { + ComputerTracker computerTimings = this.timingLookup.get( computer ); + if( computerTimings == null ) + { + computerTimings = new ComputerTracker( computer ); + this.timingLookup.put( computer, computerTimings ); + this.timings.add( computerTimings ); } - computerTimings.addValue(field, change); + computerTimings.addValue( field, change ); } } } diff --git a/src/main/java/dan200/computercraft/core/tracking/TrackingField.java b/src/main/java/dan200/computercraft/core/tracking/TrackingField.java index d4e9ef17b..2ffd29d78 100644 --- a/src/main/java/dan200/computercraft/core/tracking/TrackingField.java +++ b/src/main/java/dan200/computercraft/core/tracking/TrackingField.java @@ -11,77 +11,88 @@ import java.util.HashMap; import java.util.Map; import java.util.function.LongFunction; -public final class TrackingField { +public final class TrackingField +{ private static final Map fields = new HashMap<>(); - public static final TrackingField TASKS = TrackingField.of("tasks", x -> String.format("%4d", x)); - public static final TrackingField TOTAL_TIME = TrackingField.of("total", x -> String.format("%7.1fms", x / 1e6)); - public static final TrackingField AVERAGE_TIME = TrackingField.of("average", x -> String.format("%4.1fms", x / 1e6)); - public static final TrackingField MAX_TIME = TrackingField.of("max", x -> String.format("%5.1fms", x / 1e6)); + public static final TrackingField TASKS = TrackingField.of( "tasks", x -> String.format( "%4d", x ) ); + public static final TrackingField TOTAL_TIME = TrackingField.of( "total", x -> String.format( "%7.1fms", x / 1e6 ) ); + public static final TrackingField AVERAGE_TIME = TrackingField.of( "average", x -> String.format( "%4.1fms", x / 1e6 ) ); + public static final TrackingField MAX_TIME = TrackingField.of( "max", x -> String.format( "%5.1fms", x / 1e6 ) ); - public static final TrackingField SERVER_COUNT = TrackingField.of("server_count", x -> String.format("%4d", x)); - public static final TrackingField SERVER_TIME = TrackingField.of("server_time", x -> String.format("%7.1fms", x / 1e6)); + public static final TrackingField SERVER_COUNT = TrackingField.of( "server_count", x -> String.format( "%4d", x ) ); + public static final TrackingField SERVER_TIME = TrackingField.of( "server_time", x -> String.format( "%7.1fms", x / 1e6 ) ); - public static final TrackingField PERIPHERAL_OPS = TrackingField.of("peripheral", TrackingField::formatDefault); - public static final TrackingField FS_OPS = TrackingField.of("fs", TrackingField::formatDefault); - public static final TrackingField TURTLE_OPS = TrackingField.of("turtle", TrackingField::formatDefault); + public static final TrackingField PERIPHERAL_OPS = TrackingField.of( "peripheral", TrackingField::formatDefault ); + public static final TrackingField FS_OPS = TrackingField.of( "fs", TrackingField::formatDefault ); + public static final TrackingField TURTLE_OPS = TrackingField.of( "turtle", TrackingField::formatDefault ); - public static final TrackingField HTTP_REQUESTS = TrackingField.of("http", TrackingField::formatDefault); - public static final TrackingField COROUTINES_CREATED = TrackingField.of("coroutines_created", x -> String.format("%4d", x)); - public static final TrackingField COROUTINES_DISPOSED = TrackingField.of("coroutines_dead", x -> String.format("%4d", x)); + public static final TrackingField HTTP_REQUESTS = TrackingField.of( "http", TrackingField::formatDefault ); + public static final TrackingField COROUTINES_CREATED = TrackingField.of( "coroutines_created", x -> String.format( "%4d", x ) ); + public static final TrackingField COROUTINES_DISPOSED = TrackingField.of( "coroutines_dead", x -> String.format( "%4d", x ) ); /** * So technically a kibibyte, but let's not argue here. */ private static final int KILOBYTE_SIZE = 1024; private static final String SI_PREFIXES = "KMGT"; - public static final TrackingField HTTP_UPLOAD = TrackingField.of("http_upload", TrackingField::formatBytes); - public static final TrackingField HTTP_DOWNLOAD = TrackingField.of("http_download", TrackingField::formatBytes); - public static final TrackingField WEBSOCKET_INCOMING = TrackingField.of("websocket_incoming", TrackingField::formatBytes); - public static final TrackingField WEBSOCKET_OUTGOING = TrackingField.of("websocket_outgoing", TrackingField::formatBytes); + public static final TrackingField HTTP_UPLOAD = TrackingField.of( "http_upload", TrackingField::formatBytes ); + public static final TrackingField HTTP_DOWNLOAD = TrackingField.of( "http_download", TrackingField::formatBytes ); + public static final TrackingField WEBSOCKET_INCOMING = TrackingField.of( "websocket_incoming", TrackingField::formatBytes ); + public static final TrackingField WEBSOCKET_OUTGOING = TrackingField.of( "websocket_outgoing", TrackingField::formatBytes ); private final String id; private final String translationKey; private final LongFunction format; - private TrackingField(String id, LongFunction format) { + private TrackingField( String id, LongFunction format ) + { this.id = id; this.translationKey = "tracking_field.computercraft." + id + ".name"; this.format = format; } - public static TrackingField of(String id, LongFunction format) { - TrackingField field = new TrackingField(id, format); - fields.put(id, field); + public static TrackingField of( String id, LongFunction format ) + { + TrackingField field = new TrackingField( id, format ); + fields.put( id, field ); return field; } - public static Map fields() { - return Collections.unmodifiableMap(fields); + public static Map fields() + { + return Collections.unmodifiableMap( fields ); } - private static String formatDefault(long value) { - return String.format("%6d", value); + private static String formatDefault( long value ) + { + return String.format( "%6d", value ); } - private static String formatBytes(long bytes) { - if (bytes < 1024) { - return String.format("%10d B", bytes); + private static String formatBytes( long bytes ) + { + if( bytes < 1024 ) + { + return String.format( "%10d B", bytes ); } - int exp = (int) (Math.log(bytes) / Math.log(KILOBYTE_SIZE)); - if (exp > SI_PREFIXES.length()) { + int exp = (int) (Math.log( bytes ) / Math.log( KILOBYTE_SIZE )); + if( exp > SI_PREFIXES.length() ) + { exp = SI_PREFIXES.length(); } - return String.format("%10.1f %siB", bytes / Math.pow(KILOBYTE_SIZE, exp), SI_PREFIXES.charAt(exp - 1)); + return String.format( "%10.1f %siB", bytes / Math.pow( KILOBYTE_SIZE, exp ), SI_PREFIXES.charAt( exp - 1 ) ); } - public String id() { + public String id() + { return this.id; } - public String translationKey() { + public String translationKey() + { return this.translationKey; } - public String format(long value) { - return this.format.apply(value); + public String format( long value ) + { + return this.format.apply( value ); } } diff --git a/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java b/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java index 946c07f4d..ce687d947 100644 --- a/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java +++ b/src/main/java/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java @@ -13,10 +13,11 @@ public interface ClientUnloadWorldEvent { Event EVENT = EventFactory.createArrayBacked( ClientUnloadWorldEvent.class, callbacks -> () -> { - for( ClientUnloadWorldEvent callback : callbacks) { + for( ClientUnloadWorldEvent callback : callbacks ) + { callback.onClientUnloadWorld(); } - }); + } ); void onClientUnloadWorld(); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java index c1cfb8d0a..8ddc8dbdc 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java @@ -5,21 +5,21 @@ */ package dan200.computercraft.fabric.mixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.client.util.math.Vector3f; import net.minecraft.util.math.Quaternion; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin (AffineTransformation.class) -public interface AffineTransformationAccess { - @Accessor - Vector3f getTranslation(); +@Mixin( AffineTransformation.class ) +public interface AffineTransformationAccess +{ + @Accessor + Vector3f getTranslation(); - @Accessor - Vector3f getScale(); + @Accessor + Vector3f getScale(); - @Accessor - Quaternion getRotation1(); + @Accessor + Quaternion getRotation1(); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java index 9759c7016..fa7541eca 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/BakedQuadAccess.java @@ -5,14 +5,14 @@ */ package dan200.computercraft.fabric.mixin; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.texture.Sprite; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.texture.Sprite; - -@Mixin (BakedQuad.class) -public interface BakedQuadAccess { - @Accessor - Sprite getSprite(); +@Mixin( BakedQuad.class ) +public interface BakedQuadAccess +{ + @Accessor + Sprite getSprite(); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java index b9c44bc9c..9d86ea657 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/ChatHudAccess.java @@ -5,17 +5,17 @@ */ package dan200.computercraft.fabric.mixin; +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.text.Text; - -@Mixin (ChatHud.class) -public interface ChatHudAccess { - @Invoker - void callAddMessage(Text text, int messageId); +@Mixin( ChatHud.class ) +public interface ChatHudAccess +{ + @Invoker + void callAddMessage( Text text, int messageId ); @Invoker - void callRemoveMessage(int messageId); + void callRemoveMessage( int messageId ); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java index f5224cecd..a799fdf3a 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java @@ -5,22 +5,22 @@ */ package dan200.computercraft.fabric.mixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Arm; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; -@Mixin (HeldItemRenderer.class) -public interface HeldItemRendererAccess { - @Invoker - float callGetMapAngle(float tickDelta); +@Mixin( HeldItemRenderer.class ) +public interface HeldItemRendererAccess +{ + @Invoker + float callGetMapAngle( float tickDelta ); - @Invoker - void callRenderArm(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, Arm arm); + @Invoker + void callRenderArm( MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, Arm arm ); - @Invoker - void callRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm); + @Invoker + void callRenderArmHoldingItem( MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm ); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java index 022e55569..8ce40b911 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java @@ -5,14 +5,14 @@ */ package dan200.computercraft.fabric.mixin; +import net.minecraft.resource.ServerResourceManager; +import net.minecraft.server.MinecraftServer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.resource.ServerResourceManager; -import net.minecraft.server.MinecraftServer; - -@Mixin (MinecraftServer.class) -public interface MinecraftServerAccess { - @Accessor - ServerResourceManager getServerResourceManager(); +@Mixin( MinecraftServer.class ) +public interface MinecraftServerAccess +{ + @Accessor + ServerResourceManager getServerResourceManager(); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java index c758b5935..0dd5c35f1 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java @@ -6,26 +6,28 @@ package dan200.computercraft.fabric.mixin; import dan200.computercraft.shared.util.DropConsumer; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.block.Block; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - /** * @see Block#dropStack(World, BlockPos, ItemStack) */ -@Mixin (Block.class) -public class MixinBlock { - @Inject (method = "dropStack", - at = @At (value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z"), - cancellable = true) - private static void dropStack(World world, BlockPos pos, ItemStack stack, CallbackInfo callbackInfo) { - if (DropConsumer.onHarvestDrops(world, pos, stack)) { +@Mixin( Block.class ) +public class MixinBlock +{ + @Inject( method = "dropStack", + at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ), + cancellable = true ) + private static void dropStack( World world, BlockPos pos, ItemStack stack, CallbackInfo callbackInfo ) + { + if( DropConsumer.onHarvestDrops( world, pos, stack ) ) + { callbackInfo.cancel(); } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java index a9835de87..baee509b6 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java @@ -6,26 +6,28 @@ package dan200.computercraft.fabric.mixin; import dan200.computercraft.shared.util.DropConsumer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.minecraft.entity.Entity; -import net.minecraft.entity.ItemEntity; -import net.minecraft.item.ItemStack; - /** * @see Entity#dropStack(ItemStack, float) */ -@Mixin (Entity.class) -public class MixinEntity { - @Inject (method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;", - at = @At (value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z"), - cancellable = true) - public void dropStack(ItemStack stack, float height, CallbackInfoReturnable callbackInfo) { - if (DropConsumer.onLivingDrops((Entity) (Object) this, stack)) { - callbackInfo.setReturnValue(null); +@Mixin( Entity.class ) +public class MixinEntity +{ + @Inject( method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;", + at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ), + cancellable = true ) + public void dropStack( ItemStack stack, float height, CallbackInfoReturnable callbackInfo ) + { + if( DropConsumer.onLivingDrops( (Entity) (Object) this, stack ) ) + { + callbackInfo.setReturnValue( null ); } } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java index dfc91c6f5..675ecbaff 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java @@ -9,12 +9,8 @@ import dan200.computercraft.client.render.ItemPocketRenderer; import dan200.computercraft.client.render.ItemPrintoutRenderer; import dan200.computercraft.shared.media.items.ItemPrintout; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.HeldItemRenderer; @@ -22,36 +18,45 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.util.Arm; import net.minecraft.util.Hand; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -@Mixin (HeldItemRenderer.class) -@Environment (EnvType.CLIENT) -public class MixinHeldItemRenderer { +@Mixin( HeldItemRenderer.class ) +@Environment( EnvType.CLIENT ) +public class MixinHeldItemRenderer +{ @Shadow - private void renderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, - Arm arm) { + private void renderArmHoldingItem( MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, + Arm arm ) + { } @Shadow - private float getMapAngle(float pitch) { + private float getMapAngle( float pitch ) + { return 0; } - @Inject (method = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderFirstPersonItem(Lnet/minecraft/client/network/AbstractClientPlayerEntity;" + - "FFLnet/minecraft/util/Hand;FLnet/minecraft/item/ItemStack;FLnet/minecraft/client/util/math/MatrixStack;" + - "Lnet/minecraft/client/render/VertexConsumerProvider;I)V", - at = @At ("HEAD"), - cancellable = true) - public void renderFirstPersonItem_Injected(AbstractClientPlayerEntity player, float var2, float pitch, Hand hand, float swingProgress, - ItemStack stack, float equipProgress, MatrixStack matrixStack, VertexConsumerProvider provider, int light, - CallbackInfo callback) { - if (stack.getItem() instanceof ItemPrintout) { - ItemPrintoutRenderer.INSTANCE.renderItemFirstPerson(matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack); + @Inject( method = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderFirstPersonItem(Lnet/minecraft/client/network/AbstractClientPlayerEntity;" + + "FFLnet/minecraft/util/Hand;FLnet/minecraft/item/ItemStack;FLnet/minecraft/client/util/math/MatrixStack;" + + "Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + at = @At( "HEAD" ), + cancellable = true ) + public void renderFirstPersonItem_Injected( AbstractClientPlayerEntity player, float var2, float pitch, Hand hand, float swingProgress, + ItemStack stack, float equipProgress, MatrixStack matrixStack, VertexConsumerProvider provider, int light, + CallbackInfo callback ) + { + if( stack.getItem() instanceof ItemPrintout ) + { + ItemPrintoutRenderer.INSTANCE.renderItemFirstPerson( matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack ); callback.cancel(); - } else if (stack.getItem() instanceof ItemPocketComputer) { - ItemPocketRenderer.INSTANCE.renderItemFirstPerson(matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack); + } + else if( stack.getItem() instanceof ItemPocketComputer ) + { + ItemPocketRenderer.INSTANCE.renderItemFirstPerson( matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack ); callback.cancel(); } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java index 07bef1555..a63706f37 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java @@ -7,29 +7,30 @@ package dan200.computercraft.fabric.mixin; import dan200.computercraft.client.render.ItemPrintoutRenderer; import dan200.computercraft.shared.media.items.ItemPrintout; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.ItemFrameEntityRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.decoration.ItemFrameEntity; import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -@Mixin (ItemFrameEntityRenderer.class) -@Environment (EnvType.CLIENT) -public class MixinItemFrameEntityRenderer { - @Inject (method = "render", at = @At ("HEAD"), cancellable = true) - private void renderItem_Injected(ItemFrameEntity itemFrameEntity, float f, float g, MatrixStack matrixStack, - VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo info) { +@Mixin( ItemFrameEntityRenderer.class ) +@Environment( EnvType.CLIENT ) +public class MixinItemFrameEntityRenderer +{ + @Inject( method = "render", at = @At( "HEAD" ), cancellable = true ) + private void renderItem_Injected( ItemFrameEntity itemFrameEntity, float f, float g, MatrixStack matrixStack, + VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo info ) + { ItemStack stack = itemFrameEntity.getHeldItemStack(); - if (stack.getItem() instanceof ItemPrintout) { - ItemPrintoutRenderer.INSTANCE.renderInFrame(matrixStack, vertexConsumerProvider, stack); + if( stack.getItem() instanceof ItemPrintout ) + { + ItemPrintoutRenderer.INSTANCE.renderInFrame( matrixStack, vertexConsumerProvider, stack ); info.cancel(); } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java index c99fbe55e..8539fc6b9 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java @@ -7,6 +7,7 @@ package dan200.computercraft.fabric.mixin; import dan200.computercraft.client.FrameInfo; import dan200.computercraft.fabric.events.ClientUnloadWorldEvent; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.world.ClientWorld; import org.spongepowered.asm.mixin.Mixin; @@ -14,23 +15,24 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.client.MinecraftClient; - -@Mixin (MinecraftClient.class) +@Mixin( MinecraftClient.class ) public abstract class MixinMinecraftClient { - @Inject (method = "render", at = @At ("HEAD")) - private void onRender(CallbackInfo info) { + @Inject( method = "render", at = @At( "HEAD" ) ) + private void onRender( CallbackInfo info ) + { FrameInfo.onRenderFrame(); } - @Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At ("RETURN")) - private void disconnectAfter(Screen screen, CallbackInfo info) { + @Inject( method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At( "RETURN" ) ) + private void disconnectAfter( Screen screen, CallbackInfo info ) + { ClientUnloadWorldEvent.EVENT.invoker().onClientUnloadWorld(); } - @Inject(method = "joinWorld", at = @At("RETURN")) - private void joinWorldAfter(ClientWorld world, CallbackInfo info) { + @Inject( method = "joinWorld", at = @At( "RETURN" ) ) + private void joinWorldAfter( ClientWorld world, CallbackInfo info ) + { ClientUnloadWorldEvent.EVENT.invoker().onClientUnloadWorld(); } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java index 7092a577f..d53ba9939 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinScreen.java @@ -6,22 +6,23 @@ package dan200.computercraft.fabric.mixin; import dan200.computercraft.shared.command.ClientCommands; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.Screen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.client.gui.screen.Screen; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -@Mixin (Screen.class) -@Environment (EnvType.CLIENT) -public class MixinScreen { - @Inject (method = "sendMessage(Ljava/lang/String;Z)V", at = @At ("HEAD"), cancellable = true) - public void sendClientCommand(String message, boolean add, CallbackInfo info) { - if (ClientCommands.onClientSendMessage(message)) { +@Mixin( Screen.class ) +@Environment( EnvType.CLIENT ) +public class MixinScreen +{ + @Inject( method = "sendMessage(Ljava/lang/String;Z)V", at = @At( "HEAD" ), cancellable = true ) + public void sendClientCommand( String message, boolean add, CallbackInfo info ) + { + if( ClientCommands.onClientSendMessage( message ) ) + { info.cancel(); } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java index c028dc960..3ca7e4620 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java @@ -21,17 +21,21 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(ServerPlayerInteractionManager.class) -public class MixinServerPlayerInteractionManager { - @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;copy()Lnet/minecraft/item/ItemStack;", ordinal = 0), method = "interactBlock(Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/Hand;Lnet/minecraft/util/hit/BlockHitResult;)Lnet/minecraft/util/ActionResult;", cancellable = true) - private void interact(ServerPlayerEntity player, World world, ItemStack stack, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { +@Mixin( ServerPlayerInteractionManager.class ) +public class MixinServerPlayerInteractionManager +{ + @Inject( at = @At( value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;copy()Lnet/minecraft/item/ItemStack;", ordinal = 0 ), method = "interactBlock(Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/Hand;Lnet/minecraft/util/hit/BlockHitResult;)Lnet/minecraft/util/ActionResult;", cancellable = true ) + private void interact( ServerPlayerEntity player, World world, ItemStack stack, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir ) + { BlockPos pos = hitResult.getBlockPos(); - BlockState state = world.getBlockState(pos); - if (player.getMainHandStack().getItem() == ComputerCraftRegistry.ModItems.DISK && state.getBlock() == ComputerCraftRegistry.ModBlocks.DISK_DRIVE) { - ActionResult actionResult = state.onUse(world, player, hand, hitResult); - if (actionResult.isAccepted()) { - Criteria.ITEM_USED_ON_BLOCK.test(player, pos, stack); - cir.setReturnValue(actionResult); + BlockState state = world.getBlockState( pos ); + if( player.getMainHandStack().getItem() == ComputerCraftRegistry.ModItems.DISK && state.getBlock() == ComputerCraftRegistry.ModBlocks.DISK_DRIVE ) + { + ActionResult actionResult = state.onUse( world, player, hand, hitResult ); + if( actionResult.isAccepted() ) + { + Criteria.ITEM_USED_ON_BLOCK.test( player, pos, stack ); + cir.setReturnValue( actionResult ); } } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java index b392f0bff..ab08f7b2e 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java @@ -6,23 +6,25 @@ package dan200.computercraft.fabric.mixin; import dan200.computercraft.shared.util.DropConsumer; +import net.minecraft.entity.Entity; +import net.minecraft.server.world.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.minecraft.entity.Entity; -import net.minecraft.server.world.ServerWorld; - /** * @see ServerWorld#spawnEntity(Entity) */ -@Mixin (ServerWorld.class) -public class MixinServerWorld { - @Inject (method = "spawnEntity", at = @At ("HEAD"), cancellable = true) - public void spawnEntity(Entity entity, CallbackInfoReturnable callbackInfo) { - if (DropConsumer.onEntitySpawn(entity)) { - callbackInfo.setReturnValue(false); +@Mixin( ServerWorld.class ) +public class MixinServerWorld +{ + @Inject( method = "spawnEntity", at = @At( "HEAD" ), cancellable = true ) + public void spawnEntity( Entity entity, CallbackInfoReturnable callbackInfo ) + { + if( DropConsumer.onEntitySpawn( entity ) ) + { + callbackInfo.setReturnValue( false ); } } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java index ef8d1745f..c4fba913c 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java @@ -5,48 +5,55 @@ */ package dan200.computercraft.fabric.mixin; -import java.util.Collection; - -import javax.annotation.Nullable; - import dan200.computercraft.shared.common.TileGeneric; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; +import javax.annotation.Nullable; +import java.util.Collection; /** * Horrible bodge to ensure a {@link BlockEntity}'s world is always present when setting a TE during another TE's tick. * * Forge does this, this is just a bodge to get Fabric in line with that behaviour. */ -@Mixin (World.class) -public class MixinWorld { - @Shadow protected boolean iteratingTickingBlockEntities; +@Mixin( World.class ) +public class MixinWorld +{ + @Shadow + protected boolean iteratingTickingBlockEntities; - @Inject (method = "setBlockEntity", at = @At ("HEAD")) - public void setBlockEntity(BlockPos pos, @Nullable BlockEntity entity, CallbackInfo info) { - if (!World.isOutOfBuildLimitVertically(pos) && entity != null && !entity.isRemoved() && this.iteratingTickingBlockEntities) { - setWorld(entity, this); + @Inject( method = "setBlockEntity", at = @At( "HEAD" ) ) + public void setBlockEntity( BlockPos pos, @Nullable BlockEntity entity, CallbackInfo info ) + { + if( !World.isOutOfBuildLimitVertically( pos ) && entity != null && !entity.isRemoved() && this.iteratingTickingBlockEntities ) + { + setWorld( entity, this ); } } - private static void setWorld(BlockEntity entity, Object world) { - if (entity.getWorld() != world && entity instanceof TileGeneric) { - entity.setLocation((World) world, entity.getPos()); + private static void setWorld( BlockEntity entity, Object world ) + { + if( entity.getWorld() != world && entity instanceof TileGeneric ) + { + entity.setLocation( (World) world, entity.getPos() ); } } - @Inject (method = "addBlockEntities", at = @At ("HEAD")) - public void addBlockEntities(Collection entities, CallbackInfo info) { - if (this.iteratingTickingBlockEntities) { - for (BlockEntity entity : entities) { - setWorld(entity, this); + @Inject( method = "addBlockEntities", at = @At( "HEAD" ) ) + public void addBlockEntities( Collection entities, CallbackInfo info ) + { + if( this.iteratingTickingBlockEntities ) + { + for( BlockEntity entity : entities ) + { + setWorld( entity, this ); } } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java index a65769185..fc16eb218 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java @@ -7,42 +7,43 @@ package dan200.computercraft.fabric.mixin; import dan200.computercraft.client.render.CableHighlightRenderer; import dan200.computercraft.client.render.MonitorHighlightRenderer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -@Mixin (WorldRenderer.class) -@Environment (EnvType.CLIENT) -public class MixinWorldRenderer { - @Inject (method = "drawBlockOutline", cancellable = true, at = @At ("HEAD")) - public void drawBlockOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos blockPos, - BlockState blockState, CallbackInfo info) { - if (CableHighlightRenderer.drawHighlight(matrixStack, - vertexConsumer, - entity, - d, - e, - f, - blockPos, - blockState) || MonitorHighlightRenderer.drawHighlight(matrixStack, - vertexConsumer, - entity, - d, - e, - f, - blockPos, - blockState)) { +@Mixin( WorldRenderer.class ) +@Environment( EnvType.CLIENT ) +public class MixinWorldRenderer +{ + @Inject( method = "drawBlockOutline", cancellable = true, at = @At( "HEAD" ) ) + public void drawBlockOutline( MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos blockPos, + BlockState blockState, CallbackInfo info ) + { + if( CableHighlightRenderer.drawHighlight( matrixStack, + vertexConsumer, + entity, + d, + e, + f, + blockPos, + blockState ) || MonitorHighlightRenderer.drawHighlight( matrixStack, + vertexConsumer, + entity, + d, + e, + f, + blockPos, + blockState ) ) + { info.cancel(); } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java b/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java index dc41422ba..58a9fc4c8 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java @@ -10,8 +10,9 @@ import net.minecraft.sound.SoundEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(MusicDiscItem.class) -public interface MusicDiscItemAccessor { +@Mixin( MusicDiscItem.class ) +public interface MusicDiscItemAccessor +{ @Accessor SoundEvent getSound(); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java index 153f22707..e1aa351da 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java @@ -5,14 +5,14 @@ */ package dan200.computercraft.fabric.mixin; +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.text.Text; - -@Mixin (SignBlockEntity.class) -public interface SignBlockEntityAccess { - @Accessor - Text[] getText(); +@Mixin( SignBlockEntity.class ) +public interface SignBlockEntityAccess +{ + @Accessor + Text[] getText(); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java index fdaa67d05..87e9c7896 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/SoundEventAccess.java @@ -5,14 +5,14 @@ */ package dan200.computercraft.fabric.mixin; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.Identifier; - -@Mixin (SoundEvent.class) -public interface SoundEventAccess { - @Accessor - Identifier getId(); +@Mixin( SoundEvent.class ) +public interface SoundEventAccess +{ + @Accessor + Identifier getId(); } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java index 798606425..4c78d0161 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java @@ -5,13 +5,13 @@ */ package dan200.computercraft.fabric.mixin; +import net.minecraft.util.WorldSavePath; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import net.minecraft.util.WorldSavePath; - -@Mixin (WorldSavePath.class) -public interface WorldSavePathAccess { - @Invoker("") - static WorldSavePath createWorldSavePath(String relativePath) { throw new UnsupportedOperationException(); } +@Mixin( WorldSavePath.class ) +public interface WorldSavePathAccess +{ + @Invoker( "" ) + static WorldSavePath createWorldSavePath( String relativePath ) { throw new UnsupportedOperationException(); } } diff --git a/src/main/java/dan200/computercraft/shared/BundledRedstone.java b/src/main/java/dan200/computercraft/shared/BundledRedstone.java index e7f3e629f..8c8be9b79 100644 --- a/src/main/java/dan200/computercraft/shared/BundledRedstone.java +++ b/src/main/java/dan200/computercraft/shared/BundledRedstone.java @@ -6,54 +6,63 @@ package dan200.computercraft.shared; -import java.util.LinkedHashSet; -import java.util.Objects; -import java.util.Set; - -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.redstone.IBundledRedstoneProvider; import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; - import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public final class BundledRedstone { +import javax.annotation.Nonnull; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + +public final class BundledRedstone +{ private static final Set providers = new LinkedHashSet<>(); private BundledRedstone() {} - public static synchronized void register(@Nonnull IBundledRedstoneProvider provider) { - Objects.requireNonNull(provider, "provider cannot be null"); - providers.add(provider); + public static synchronized void register( @Nonnull IBundledRedstoneProvider provider ) + { + Objects.requireNonNull( provider, "provider cannot be null" ); + providers.add( provider ); } - public static int getDefaultOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side) { - return World.isInBuildLimit(pos) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput(world, pos, side) : -1; + public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) + { + return World.isInBuildLimit( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1; } - public static int getOutput(World world, BlockPos pos, Direction side) { - int signal = getUnmaskedOutput(world, pos, side); + public static int getOutput( World world, BlockPos pos, Direction side ) + { + int signal = getUnmaskedOutput( world, pos, side ); return signal >= 0 ? signal : 0; } - private static int getUnmaskedOutput(World world, BlockPos pos, Direction side) { - if (!World.isInBuildLimit(pos)) { + private static int getUnmaskedOutput( World world, BlockPos pos, Direction side ) + { + if( !World.isInBuildLimit( pos ) ) + { return -1; } // Try the providers in order: int combinedSignal = -1; - for (IBundledRedstoneProvider bundledRedstoneProvider : providers) { - try { - int signal = bundledRedstoneProvider.getBundledRedstoneOutput(world, pos, side); - if (signal >= 0) { + for( IBundledRedstoneProvider bundledRedstoneProvider : providers ) + { + try + { + int signal = bundledRedstoneProvider.getBundledRedstoneOutput( world, pos, side ); + if( signal >= 0 ) + { combinedSignal = combinedSignal < 0 ? signal & 0xffff : combinedSignal | (signal & 0xffff); } - } catch (Exception e) { - ComputerCraft.log.error("Bundled redstone provider " + bundledRedstoneProvider + " errored.", e); + } + catch( Exception e ) + { + ComputerCraft.log.error( "Bundled redstone provider " + bundledRedstoneProvider + " errored.", e ); } } diff --git a/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java b/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java index 6b7147242..3e45b482f 100644 --- a/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java +++ b/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java @@ -6,13 +6,6 @@ package dan200.computercraft.shared; -import static net.minecraft.util.registry.Registry.BLOCK_ENTITY_TYPE; - -import java.util.Objects; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.shared.common.ContainerHeldItem; @@ -29,11 +22,7 @@ import dan200.computercraft.shared.media.items.ItemTreasureDisk; import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive; import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; 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.wired.ItemBlockCable; -import dan200.computercraft.shared.peripheral.modem.wired.TileCable; -import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull; +import dan200.computercraft.shared.peripheral.modem.wired.*; import dan200.computercraft.shared.peripheral.modem.wireless.BlockWirelessModem; import dan200.computercraft.shared.peripheral.modem.wireless.TileWirelessModem; import dan200.computercraft.shared.peripheral.monitor.BlockMonitor; @@ -54,7 +43,8 @@ import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import dan200.computercraft.shared.turtle.items.ItemTurtle; import dan200.computercraft.shared.turtle.upgrades.*; import dan200.computercraft.shared.util.FixedPointTileEntityType; - +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.Blocks; @@ -73,234 +63,258 @@ import net.minecraft.sound.BlockSoundGroup; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; -import org.apache.http.client.utils.Idn; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; -public final class ComputerCraftRegistry { +import static net.minecraft.util.registry.Registry.BLOCK_ENTITY_TYPE; + +public final class ComputerCraftRegistry +{ public static final String MOD_ID = ComputerCraft.MOD_ID; - public static void init() { + public static void init() + { Object[] o = { ModTiles.CABLE, ModBlocks.CABLE, ModItems.CABLE, ModEntities.TURTLE_PLAYER, ModContainers.COMPUTER, - }; + }; TurtleUpgrades.registerTurtleUpgrades(); PocketUpgrades.registerPocketUpgrades(); } - public static final class ModBlocks { - public static final BlockComputer COMPUTER_NORMAL = register("computer_normal", - new BlockComputer(properties(), ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL)); - public static final BlockComputer COMPUTER_ADVANCED = register("computer_advanced", - new BlockComputer(properties(), - ComputerFamily.ADVANCED, - ModTiles.COMPUTER_ADVANCED)); - public static final BlockComputer COMPUTER_COMMAND = register("computer_command", - new BlockComputer(FabricBlockSettings.copyOf(Blocks.STONE) - .strength(-1, 6000000.0F), - ComputerFamily.COMMAND, - ModTiles.COMPUTER_COMMAND)); - public static final BlockTurtle TURTLE_NORMAL = register("turtle_normal", - new BlockTurtle(turtleProperties(), ComputerFamily.NORMAL, ModTiles.TURTLE_NORMAL)); - public static final BlockTurtle TURTLE_ADVANCED = register("turtle_advanced", - new BlockTurtle(turtleProperties(), ComputerFamily.ADVANCED, ModTiles.TURTLE_ADVANCED)); - public static final BlockSpeaker SPEAKER = register("speaker", new BlockSpeaker(properties())); - public static final BlockDiskDrive DISK_DRIVE = register("disk_drive", new BlockDiskDrive(properties())); - public static final BlockPrinter PRINTER = register("printer", new BlockPrinter(properties())); - public static final BlockMonitor MONITOR_NORMAL = register("monitor_normal", new BlockMonitor(properties(), ModTiles.MONITOR_NORMAL)); - public static final BlockMonitor MONITOR_ADVANCED = register("monitor_advanced", new BlockMonitor(properties(), ModTiles.MONITOR_ADVANCED)); - public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = register("wireless_modem_normal", - new BlockWirelessModem(properties(), ModTiles.WIRELESS_MODEM_NORMAL)); - public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = register("wireless_modem_advanced", - new BlockWirelessModem(properties(), ModTiles.WIRELESS_MODEM_ADVANCED)); - public static final BlockWiredModemFull WIRED_MODEM_FULL = register("wired_modem_full", - new BlockWiredModemFull(emProperties(), ModTiles.WIRED_MODEM_FULL)); - public static final BlockCable CABLE = register("cable", new BlockCable(emProperties())); + public static final class ModBlocks + { + public static final BlockComputer COMPUTER_NORMAL = register( "computer_normal", + new BlockComputer( properties(), ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL ) ); + public static final BlockComputer COMPUTER_ADVANCED = register( "computer_advanced", + new BlockComputer( properties(), + ComputerFamily.ADVANCED, + ModTiles.COMPUTER_ADVANCED ) ); + public static final BlockComputer COMPUTER_COMMAND = register( "computer_command", + new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE ) + .strength( -1, 6000000.0F ), + ComputerFamily.COMMAND, + ModTiles.COMPUTER_COMMAND ) ); + public static final BlockTurtle TURTLE_NORMAL = register( "turtle_normal", + new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, ModTiles.TURTLE_NORMAL ) ); + public static final BlockTurtle TURTLE_ADVANCED = register( "turtle_advanced", + new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, ModTiles.TURTLE_ADVANCED ) ); + public static final BlockSpeaker SPEAKER = register( "speaker", new BlockSpeaker( properties() ) ); + public static final BlockDiskDrive DISK_DRIVE = register( "disk_drive", new BlockDiskDrive( properties() ) ); + public static final BlockPrinter PRINTER = register( "printer", new BlockPrinter( properties() ) ); + public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL ) ); + public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED ) ); + public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = register( "wireless_modem_normal", + new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_NORMAL ) ); + public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = register( "wireless_modem_advanced", + new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_ADVANCED ) ); + public static final BlockWiredModemFull WIRED_MODEM_FULL = register( "wired_modem_full", + new BlockWiredModemFull( emProperties(), ModTiles.WIRED_MODEM_FULL ) ); + public static final BlockCable CABLE = register( "cable", new BlockCable( emProperties() ) ); - private static Block.Settings properties() { + private static Block.Settings properties() + { //return FabricBlockSettings.copyOf(Blocks.GLASS) - // .strength(2); - return AbstractBlock.Settings.of(Material.GLASS) - .strength(2F) - .sounds(BlockSoundGroup.STONE) + // .strength(2); + return AbstractBlock.Settings.of( Material.GLASS ) + .strength( 2F ) + .sounds( BlockSoundGroup.STONE ) .nonOpaque(); } - private static Block.Settings turtleProperties() { - return FabricBlockSettings.copyOf(Blocks.STONE) - .strength(2.5f); + private static Block.Settings turtleProperties() + { + return FabricBlockSettings.copyOf( Blocks.STONE ) + .strength( 2.5f ); } - private static Block.Settings emProperties() { - return FabricBlockSettings.copyOf(Blocks.STONE) - .strength(1.5f); + private static Block.Settings emProperties() + { + return FabricBlockSettings.copyOf( Blocks.STONE ) + .strength( 1.5f ); } - public static T register(String id, T value) { - return Registry.register(Registry.BLOCK, new Identifier(MOD_ID, id), value); + public static T register( String id, T value ) + { + return Registry.register( Registry.BLOCK, new Identifier( MOD_ID, id ), value ); } } - public static class ModTiles { + public static class ModTiles + { - public static final BlockEntityType MONITOR_NORMAL = ofBlock(() -> ModBlocks.MONITOR_NORMAL, - "monitor_normal", - f -> new TileMonitor(f, false)); - public static final BlockEntityType MONITOR_ADVANCED = ofBlock(() -> ModBlocks.MONITOR_ADVANCED, - "monitor_advanced", - f -> new TileMonitor(f, true)); - public static final BlockEntityType COMPUTER_NORMAL = ofBlock(() -> ModBlocks.COMPUTER_NORMAL, - "computer_normal", - f -> new TileComputer(ComputerFamily.NORMAL, f)); - public static final BlockEntityType COMPUTER_ADVANCED = ofBlock(() -> ModBlocks.COMPUTER_ADVANCED, - "computer_advanced", - f -> new TileComputer(ComputerFamily.ADVANCED, f)); - public static final BlockEntityType COMPUTER_COMMAND = ofBlock(() -> ModBlocks.COMPUTER_COMMAND, - "computer_command", - f -> new TileCommandComputer(ComputerFamily.COMMAND, f)); - public static final BlockEntityType TURTLE_NORMAL = ofBlock(() -> ModBlocks.TURTLE_NORMAL, - "turtle_normal", - f -> new TileTurtle(f, ComputerFamily.NORMAL)); - public static final BlockEntityType TURTLE_ADVANCED = ofBlock(() -> ModBlocks.TURTLE_ADVANCED, - "turtle_advanced", - f -> new TileTurtle(f, ComputerFamily.ADVANCED)); - public static final BlockEntityType SPEAKER = ofBlock(() -> ModBlocks.SPEAKER, "speaker", TileSpeaker::new); - public static final BlockEntityType DISK_DRIVE = ofBlock(() -> ModBlocks.DISK_DRIVE, "disk_drive", TileDiskDrive::new); - public static final BlockEntityType PRINTER = ofBlock(() -> ModBlocks.PRINTER, "printer", TilePrinter::new); - public static final BlockEntityType WIRED_MODEM_FULL = ofBlock(() -> ModBlocks.WIRED_MODEM_FULL, - "wired_modem_full", - TileWiredModemFull::new); - public static final BlockEntityType CABLE = ofBlock(() -> ModBlocks.CABLE, "cable", TileCable::new); - public static final BlockEntityType WIRELESS_MODEM_NORMAL = ofBlock(() -> ModBlocks.WIRELESS_MODEM_NORMAL, - "wireless_modem_normal", - f -> new TileWirelessModem(f, false)); - public static final BlockEntityType WIRELESS_MODEM_ADVANCED = ofBlock(() -> ModBlocks.WIRELESS_MODEM_ADVANCED, - "wireless_modem_advanced", - f -> new TileWirelessModem(f, true)); + public static final BlockEntityType MONITOR_NORMAL = ofBlock( () -> ModBlocks.MONITOR_NORMAL, + "monitor_normal", + f -> new TileMonitor( f, false ) ); + public static final BlockEntityType MONITOR_ADVANCED = ofBlock( () -> ModBlocks.MONITOR_ADVANCED, + "monitor_advanced", + f -> new TileMonitor( f, true ) ); + public static final BlockEntityType COMPUTER_NORMAL = ofBlock( () -> ModBlocks.COMPUTER_NORMAL, + "computer_normal", + f -> new TileComputer( ComputerFamily.NORMAL, f ) ); + public static final BlockEntityType COMPUTER_ADVANCED = ofBlock( () -> ModBlocks.COMPUTER_ADVANCED, + "computer_advanced", + f -> new TileComputer( ComputerFamily.ADVANCED, f ) ); + public static final BlockEntityType COMPUTER_COMMAND = ofBlock( () -> ModBlocks.COMPUTER_COMMAND, + "computer_command", + f -> new TileCommandComputer( ComputerFamily.COMMAND, f ) ); + public static final BlockEntityType TURTLE_NORMAL = ofBlock( () -> ModBlocks.TURTLE_NORMAL, + "turtle_normal", + f -> new TileTurtle( f, ComputerFamily.NORMAL ) ); + public static final BlockEntityType TURTLE_ADVANCED = ofBlock( () -> ModBlocks.TURTLE_ADVANCED, + "turtle_advanced", + f -> new TileTurtle( f, ComputerFamily.ADVANCED ) ); + public static final BlockEntityType SPEAKER = ofBlock( () -> ModBlocks.SPEAKER, "speaker", TileSpeaker::new ); + public static final BlockEntityType DISK_DRIVE = ofBlock( () -> ModBlocks.DISK_DRIVE, "disk_drive", TileDiskDrive::new ); + public static final BlockEntityType PRINTER = ofBlock( () -> ModBlocks.PRINTER, "printer", TilePrinter::new ); + public static final BlockEntityType WIRED_MODEM_FULL = ofBlock( () -> ModBlocks.WIRED_MODEM_FULL, + "wired_modem_full", + TileWiredModemFull::new ); + public static final BlockEntityType CABLE = ofBlock( () -> ModBlocks.CABLE, "cable", TileCable::new ); + public static final BlockEntityType WIRELESS_MODEM_NORMAL = ofBlock( () -> ModBlocks.WIRELESS_MODEM_NORMAL, + "wireless_modem_normal", + f -> new TileWirelessModem( f, false ) ); + public static final BlockEntityType WIRELESS_MODEM_ADVANCED = ofBlock( () -> ModBlocks.WIRELESS_MODEM_ADVANCED, + "wireless_modem_advanced", + f -> new TileWirelessModem( f, true ) ); - private static BlockEntityType ofBlock(Supplier block, String id, Function, T> factory) { - return Registry.register(BLOCK_ENTITY_TYPE, - new Identifier(MOD_ID, id), - FixedPointTileEntityType.create(Objects.requireNonNull(block), factory)); + private static BlockEntityType ofBlock( Supplier block, String id, Function, T> factory ) + { + return Registry.register( BLOCK_ENTITY_TYPE, + new Identifier( MOD_ID, id ), + FixedPointTileEntityType.create( Objects.requireNonNull( block ), factory ) ); } } - public static final class ModItems { + public static final class ModItems + { private static final ItemGroup mainItemGroup = ComputerCraft.MAIN_GROUP; - public static final ItemComputer COMPUTER_NORMAL = ofBlock(ModBlocks.COMPUTER_NORMAL, ItemComputer::new); - public static final ItemComputer COMPUTER_ADVANCED = ofBlock(ModBlocks.COMPUTER_ADVANCED, ItemComputer::new); - public static final ItemComputer COMPUTER_COMMAND = ofBlock(ModBlocks.COMPUTER_COMMAND, ItemComputer::new); - public static final ItemPocketComputer POCKET_COMPUTER_NORMAL = register("pocket_computer_normal", - new ItemPocketComputer(properties().maxCount(1), ComputerFamily.NORMAL)); - public static final ItemPocketComputer POCKET_COMPUTER_ADVANCED = register("pocket_computer_advanced", - new ItemPocketComputer(properties().maxCount(1), - ComputerFamily.ADVANCED)); - public static final ItemTurtle TURTLE_NORMAL = ofBlock(ModBlocks.TURTLE_NORMAL, ItemTurtle::new); - public static final ItemTurtle TURTLE_ADVANCED = ofBlock(ModBlocks.TURTLE_ADVANCED, ItemTurtle::new); - public static final ItemDisk DISK = register("disk", new ItemDisk(properties().maxCount(1))); - public static final ItemTreasureDisk TREASURE_DISK = register("treasure_disk", new ItemTreasureDisk(properties().maxCount(1))); - public static final ItemPrintout PRINTED_PAGE = register("printed_page", new ItemPrintout(properties().maxCount(1), ItemPrintout.Type.PAGE)); - public static final ItemPrintout PRINTED_PAGES = register("printed_pages", new ItemPrintout(properties().maxCount(1), ItemPrintout.Type.PAGES)); - public static final ItemPrintout PRINTED_BOOK = register("printed_book", new ItemPrintout(properties().maxCount(1), ItemPrintout.Type.BOOK)); - public static final BlockItem SPEAKER = ofBlock(ModBlocks.SPEAKER, BlockItem::new); - public static final BlockItem DISK_DRIVE = ofBlock(ModBlocks.DISK_DRIVE, BlockItem::new); - public static final BlockItem PRINTER = ofBlock(ModBlocks.PRINTER, BlockItem::new); - public static final BlockItem MONITOR_NORMAL = ofBlock(ModBlocks.MONITOR_NORMAL, BlockItem::new); - public static final BlockItem MONITOR_ADVANCED = ofBlock(ModBlocks.MONITOR_ADVANCED, BlockItem::new); - public static final BlockItem WIRELESS_MODEM_NORMAL = ofBlock(ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new); - public static final BlockItem WIRELESS_MODEM_ADVANCED = ofBlock(ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new); - public static final BlockItem WIRED_MODEM_FULL = ofBlock(ModBlocks.WIRED_MODEM_FULL, BlockItem::new); - public static final ItemBlockCable.Cable CABLE = register("cable", new ItemBlockCable.Cable(ModBlocks.CABLE, properties())); - public static final ItemBlockCable.WiredModem WIRED_MODEM = register("wired_modem", new ItemBlockCable.WiredModem(ModBlocks.CABLE, properties())); + public static final ItemComputer COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL, ItemComputer::new ); + public static final ItemComputer COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED, ItemComputer::new ); + public static final ItemComputer COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND, ItemComputer::new ); + public static final ItemPocketComputer POCKET_COMPUTER_NORMAL = register( "pocket_computer_normal", + new ItemPocketComputer( properties().maxCount( 1 ), ComputerFamily.NORMAL ) ); + public static final ItemPocketComputer POCKET_COMPUTER_ADVANCED = register( "pocket_computer_advanced", + new ItemPocketComputer( properties().maxCount( 1 ), + ComputerFamily.ADVANCED ) ); + public static final ItemTurtle TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL, ItemTurtle::new ); + public static final ItemTurtle TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED, ItemTurtle::new ); + public static final ItemDisk DISK = register( "disk", new ItemDisk( properties().maxCount( 1 ) ) ); + public static final ItemTreasureDisk TREASURE_DISK = register( "treasure_disk", new ItemTreasureDisk( properties().maxCount( 1 ) ) ); + public static final ItemPrintout PRINTED_PAGE = register( "printed_page", new ItemPrintout( properties().maxCount( 1 ), ItemPrintout.Type.PAGE ) ); + public static final ItemPrintout PRINTED_PAGES = register( "printed_pages", new ItemPrintout( properties().maxCount( 1 ), ItemPrintout.Type.PAGES ) ); + public static final ItemPrintout PRINTED_BOOK = register( "printed_book", new ItemPrintout( properties().maxCount( 1 ), ItemPrintout.Type.BOOK ) ); + public static final BlockItem SPEAKER = ofBlock( ModBlocks.SPEAKER, BlockItem::new ); + public static final BlockItem DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, BlockItem::new ); + public static final BlockItem PRINTER = ofBlock( ModBlocks.PRINTER, BlockItem::new ); + public static final BlockItem MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL, BlockItem::new ); + public static final BlockItem MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED, BlockItem::new ); + public static final BlockItem WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new ); + public static final BlockItem WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new ); + public static final BlockItem WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL, BlockItem::new ); + public static final ItemBlockCable.Cable CABLE = register( "cable", new ItemBlockCable.Cable( ModBlocks.CABLE, properties() ) ); + public static final ItemBlockCable.WiredModem WIRED_MODEM = register( "wired_modem", new ItemBlockCable.WiredModem( ModBlocks.CABLE, properties() ) ); - private static I ofBlock(B parent, BiFunction supplier) { - return Registry.register(Registry.ITEM, Registry.BLOCK.getId(parent), supplier.apply(parent, properties())); + private static I ofBlock( B parent, BiFunction supplier ) + { + return Registry.register( Registry.ITEM, Registry.BLOCK.getId( parent ), supplier.apply( parent, properties() ) ); } - private static Item.Settings properties() { - return new Item.Settings().group(mainItemGroup); + private static Item.Settings properties() + { + return new Item.Settings().group( mainItemGroup ); } - private static T register(String id, T item) { - return Registry.register(Registry.ITEM, new Identifier(MOD_ID, id), item); + private static T register( String id, T item ) + { + return Registry.register( Registry.ITEM, new Identifier( MOD_ID, id ), item ); } } - public static class ModEntities { - public static final EntityType TURTLE_PLAYER = Registry.register(Registry.ENTITY_TYPE, - new Identifier(MOD_ID, "turtle_player"), - EntityType.Builder.create(SpawnGroup.MISC).disableSaving() - .disableSummon() - .setDimensions( - 0, - 0) - .build( - ComputerCraft.MOD_ID + ":turtle_player")); + public static class ModEntities + { + public static final EntityType TURTLE_PLAYER = Registry.register( Registry.ENTITY_TYPE, + new Identifier( MOD_ID, "turtle_player" ), + EntityType.Builder.create( SpawnGroup.MISC ).disableSaving() + .disableSummon() + .setDimensions( + 0, + 0 ) + .build( + ComputerCraft.MOD_ID + ":turtle_player" ) ); } - public static class ModContainers { - public static final ScreenHandlerType COMPUTER = registerExtended("computer", ContainerComputer::new); - public static final ScreenHandlerType POCKET_COMPUTER = registerExtended("pocket_computer", ContainerPocketComputer::new); - public static final ScreenHandlerType TURTLE = registerExtended("turtle", ContainerTurtle::new); - public static final ScreenHandlerType DISK_DRIVE = registerSimple("disk_drive", ContainerDiskDrive::new); - public static final ScreenHandlerType PRINTER = registerSimple("printer", ContainerPrinter::new); - public static final ScreenHandlerType PRINTOUT = registerExtended("printout", ContainerHeldItem::createPrintout); - public static final ScreenHandlerType VIEW_COMPUTER = registerExtended("view_computer", ContainerViewComputer::new); + public static class ModContainers + { + public static final ScreenHandlerType COMPUTER = registerExtended( "computer", ContainerComputer::new ); + public static final ScreenHandlerType POCKET_COMPUTER = registerExtended( "pocket_computer", ContainerPocketComputer::new ); + public static final ScreenHandlerType TURTLE = registerExtended( "turtle", ContainerTurtle::new ); + public static final ScreenHandlerType DISK_DRIVE = registerSimple( "disk_drive", ContainerDiskDrive::new ); + public static final ScreenHandlerType PRINTER = registerSimple( "printer", ContainerPrinter::new ); + public static final ScreenHandlerType PRINTOUT = registerExtended( "printout", ContainerHeldItem::createPrintout ); + public static final ScreenHandlerType VIEW_COMPUTER = registerExtended( "view_computer", ContainerViewComputer::new ); - private static ScreenHandlerType registerSimple(String id, - ScreenHandlerRegistry.SimpleClientHandlerFactory function) { - return ScreenHandlerRegistry.registerSimple(new Identifier(MOD_ID, id), function); + private static ScreenHandlerType registerSimple( String id, + ScreenHandlerRegistry.SimpleClientHandlerFactory function ) + { + return ScreenHandlerRegistry.registerSimple( new Identifier( MOD_ID, id ), function ); } - private static ScreenHandlerType registerExtended(String id, ScreenHandlerRegistry.ExtendedClientHandlerFactory function) { - return ScreenHandlerRegistry.registerExtended(new Identifier(MOD_ID, id), function); + private static ScreenHandlerType registerExtended( String id, ScreenHandlerRegistry.ExtendedClientHandlerFactory function ) + { + return ScreenHandlerRegistry.registerExtended( new Identifier( MOD_ID, id ), function ); } } - public static final class TurtleUpgrades { - public static TurtleModem wirelessModemNormal = new TurtleModem(false, new Identifier(ComputerCraft.MOD_ID, "wireless_modem_normal")); - public static TurtleModem wirelessModemAdvanced = new TurtleModem(true, new Identifier(ComputerCraft.MOD_ID, "wireless_modem_advanced")); - public static TurtleSpeaker speaker = new TurtleSpeaker(new Identifier(ComputerCraft.MOD_ID, "speaker")); + public static final class TurtleUpgrades + { + public static TurtleModem wirelessModemNormal = new TurtleModem( false, new Identifier( ComputerCraft.MOD_ID, "wireless_modem_normal" ) ); + public static TurtleModem wirelessModemAdvanced = new TurtleModem( true, new Identifier( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) ); + public static TurtleSpeaker speaker = new TurtleSpeaker( new Identifier( ComputerCraft.MOD_ID, "speaker" ) ); - public static TurtleCraftingTable craftingTable = new TurtleCraftingTable(new Identifier("minecraft", "crafting_table")); - public static TurtleSword diamondSword = new TurtleSword(new Identifier("minecraft", "diamond_sword"), Items.DIAMOND_SWORD); - public static TurtleShovel diamondShovel = new TurtleShovel(new Identifier("minecraft", "diamond_shovel"), Items.DIAMOND_SHOVEL); - public static TurtleTool diamondPickaxe = new TurtleTool(new Identifier("minecraft", "diamond_pickaxe"), Items.DIAMOND_PICKAXE); - public static TurtleAxe diamondAxe = new TurtleAxe(new Identifier("minecraft", "diamond_axe"), Items.DIAMOND_AXE); - public static TurtleHoe diamondHoe = new TurtleHoe(new Identifier("minecraft", "diamond_hoe"), Items.DIAMOND_HOE); + public static TurtleCraftingTable craftingTable = new TurtleCraftingTable( new Identifier( "minecraft", "crafting_table" ) ); + public static TurtleSword diamondSword = new TurtleSword( new Identifier( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD ); + public static TurtleShovel diamondShovel = new TurtleShovel( new Identifier( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL ); + public static TurtleTool diamondPickaxe = new TurtleTool( new Identifier( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE ); + public static TurtleAxe diamondAxe = new TurtleAxe( new Identifier( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE ); + public static TurtleHoe diamondHoe = new TurtleHoe( new Identifier( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE ); - public static TurtleTool netheritePickaxe = new TurtleTool(new Identifier("minecraft", "netherite_pickaxe"), Items.NETHERITE_PICKAXE); + public static TurtleTool netheritePickaxe = new TurtleTool( new Identifier( "minecraft", "netherite_pickaxe" ), Items.NETHERITE_PICKAXE ); - public static void registerTurtleUpgrades() { - ComputerCraftAPI.registerTurtleUpgrade(wirelessModemNormal); - ComputerCraftAPI.registerTurtleUpgrade(wirelessModemAdvanced); - ComputerCraftAPI.registerTurtleUpgrade(speaker); + public static void registerTurtleUpgrades() + { + ComputerCraftAPI.registerTurtleUpgrade( wirelessModemNormal ); + ComputerCraftAPI.registerTurtleUpgrade( wirelessModemAdvanced ); + ComputerCraftAPI.registerTurtleUpgrade( speaker ); - ComputerCraftAPI.registerTurtleUpgrade(craftingTable); - ComputerCraftAPI.registerTurtleUpgrade(diamondSword); - ComputerCraftAPI.registerTurtleUpgrade(diamondShovel); - ComputerCraftAPI.registerTurtleUpgrade(diamondPickaxe); - ComputerCraftAPI.registerTurtleUpgrade(diamondAxe); - ComputerCraftAPI.registerTurtleUpgrade(diamondHoe); + ComputerCraftAPI.registerTurtleUpgrade( craftingTable ); + ComputerCraftAPI.registerTurtleUpgrade( diamondSword ); + ComputerCraftAPI.registerTurtleUpgrade( diamondShovel ); + ComputerCraftAPI.registerTurtleUpgrade( diamondPickaxe ); + ComputerCraftAPI.registerTurtleUpgrade( diamondAxe ); + ComputerCraftAPI.registerTurtleUpgrade( diamondHoe ); - ComputerCraftAPI.registerTurtleUpgrade(netheritePickaxe); + ComputerCraftAPI.registerTurtleUpgrade( netheritePickaxe ); } } - public static final class PocketUpgrades { - public static PocketModem wirelessModemNormal = new PocketModem(false); - public static PocketModem wirelessModemAdvanced = new PocketModem(true); + public static final class PocketUpgrades + { + public static PocketModem wirelessModemNormal = new PocketModem( false ); + public static PocketModem wirelessModemAdvanced = new PocketModem( true ); public static PocketSpeaker speaker = new PocketSpeaker(); - public static void registerPocketUpgrades() { - ComputerCraftAPI.registerPocketUpgrade(wirelessModemNormal); - ComputerCraftAPI.registerPocketUpgrade(wirelessModemAdvanced); - ComputerCraftAPI.registerPocketUpgrade(speaker); + public static void registerPocketUpgrades() + { + ComputerCraftAPI.registerPocketUpgrade( wirelessModemNormal ); + ComputerCraftAPI.registerPocketUpgrade( wirelessModemAdvanced ); + ComputerCraftAPI.registerPocketUpgrade( speaker ); } } diff --git a/src/main/java/dan200/computercraft/shared/MediaProviders.java b/src/main/java/dan200/computercraft/shared/MediaProviders.java index 35f1682dc..a76eef0be 100644 --- a/src/main/java/dan200/computercraft/shared/MediaProviders.java +++ b/src/main/java/dan200/computercraft/shared/MediaProviders.java @@ -6,43 +6,50 @@ package dan200.computercraft.shared; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.api.media.IMediaProvider; +import net.minecraft.item.ItemStack; + +import javax.annotation.Nonnull; import java.util.LinkedHashSet; import java.util.Objects; import java.util.Set; -import javax.annotation.Nonnull; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.media.IMediaProvider; - -import net.minecraft.item.ItemStack; - -public final class MediaProviders { +public final class MediaProviders +{ private static final Set providers = new LinkedHashSet<>(); private MediaProviders() {} - public static synchronized void register(@Nonnull IMediaProvider provider) { - Objects.requireNonNull(provider, "provider cannot be null"); - providers.add(provider); + public static synchronized void register( @Nonnull IMediaProvider provider ) + { + Objects.requireNonNull( provider, "provider cannot be null" ); + providers.add( provider ); } - public static IMedia get(@Nonnull ItemStack stack) { - if (stack.isEmpty()) { + public static IMedia get( @Nonnull ItemStack stack ) + { + if( stack.isEmpty() ) + { return null; } // Try the handlers in order: - for (IMediaProvider mediaProvider : providers) { - try { - IMedia media = mediaProvider.getMedia(stack); - if (media != null) { + for( IMediaProvider mediaProvider : providers ) + { + try + { + IMedia media = mediaProvider.getMedia( stack ); + if( media != null ) + { return media; } - } catch (Exception e) { + } + catch( Exception e ) + { // mod misbehaved, ignore it - ComputerCraft.log.error("Media provider " + mediaProvider + " errored.", e); + ComputerCraft.log.error( "Media provider " + mediaProvider + " errored.", e ); } } return null; diff --git a/src/main/java/dan200/computercraft/shared/Peripherals.java b/src/main/java/dan200/computercraft/shared/Peripherals.java index 0db0e06f7..38fc5676e 100644 --- a/src/main/java/dan200/computercraft/shared/Peripherals.java +++ b/src/main/java/dan200/computercraft/shared/Peripherals.java @@ -6,53 +6,59 @@ package dan200.computercraft.shared; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Objects; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheralProvider; - import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public final class Peripherals { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Objects; + +public final class Peripherals +{ private static final Collection providers = new LinkedHashSet<>(); private Peripherals() {} - public static synchronized void register(@Nonnull IPeripheralProvider provider) { - Objects.requireNonNull(provider, "provider cannot be null"); - providers.add(provider); + public static synchronized void register( @Nonnull IPeripheralProvider provider ) + { + Objects.requireNonNull( provider, "provider cannot be null" ); + providers.add( provider ); } @Nullable - public static IPeripheral getPeripheral(World world, BlockPos pos, Direction side) { - return World.isInBuildLimit(pos) && !world.isClient ? getPeripheralAt(world, pos, side) : null; + public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side ) + { + return World.isInBuildLimit( pos ) && !world.isClient ? getPeripheralAt( world, pos, side ) : null; } @Nullable - private static IPeripheral getPeripheralAt(World world, BlockPos pos, Direction side) { + private static IPeripheral getPeripheralAt( World world, BlockPos pos, Direction side ) + { // Try the handlers in order: - for (IPeripheralProvider peripheralProvider : providers) { - try { - IPeripheral peripheral = peripheralProvider.getPeripheral(world, pos, side); - if (peripheral != null) { + for( IPeripheralProvider peripheralProvider : providers ) + { + try + { + IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side ); + if( peripheral != null ) + { return peripheral; } - } catch (Exception e) { - ComputerCraft.log.error("Peripheral provider " + peripheralProvider + " errored.", e); + } + catch( Exception e ) + { + ComputerCraft.log.error( "Peripheral provider " + peripheralProvider + " errored.", e ); } } - return GenericPeripheralProvider.getPeripheral(world, pos, side); + return GenericPeripheralProvider.getPeripheral( world, pos, side ); } } diff --git a/src/main/java/dan200/computercraft/shared/PocketUpgrades.java b/src/main/java/dan200/computercraft/shared/PocketUpgrades.java index 6704ac02b..0c5820bea 100644 --- a/src/main/java/dan200/computercraft/shared/PocketUpgrades.java +++ b/src/main/java/dan200/computercraft/shared/PocketUpgrades.java @@ -38,7 +38,7 @@ public final class PocketUpgrades // Infer the mod id by the identifier of the upgrade. This is not how the forge api works, so it may break peripheral mods using the api. // TODO: get the mod id of the mod that is currently being loaded. - ModContainer mc = FabricLoader.getInstance().getModContainer(upgrade.getUpgradeID().getNamespace()).orElseGet(null); + ModContainer mc = FabricLoader.getInstance().getModContainer( upgrade.getUpgradeID().getNamespace() ).orElseGet( null ); if( mc != null && mc.getMetadata().getId() != null ) upgradeOwners.put( upgrade, mc.getMetadata().getId() ); } @@ -85,4 +85,4 @@ public final class PocketUpgrades { return Collections.unmodifiableCollection( upgrades.values() ); } -} \ No newline at end of file +} diff --git a/src/main/java/dan200/computercraft/shared/TurtlePermissions.java b/src/main/java/dan200/computercraft/shared/TurtlePermissions.java index baf466be3..f6236a770 100644 --- a/src/main/java/dan200/computercraft/shared/TurtlePermissions.java +++ b/src/main/java/dan200/computercraft/shared/TurtlePermissions.java @@ -9,27 +9,31 @@ package dan200.computercraft.shared; import com.google.common.eventbus.Subscribe; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.event.TurtleActionEvent; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public final class TurtlePermissions { - public static boolean isBlockEditable(World world, BlockPos pos, PlayerEntity player) { - return isBlockEnterable(world, pos, player); +public final class TurtlePermissions +{ + public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player ) + { + return isBlockEnterable( world, pos, player ); } - public static boolean isBlockEnterable(World world, BlockPos pos, PlayerEntity player) { + public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player ) + { MinecraftServer server = world.getServer(); - return server == null || world.isClient || (world instanceof ServerWorld && !server.isSpawnProtected((ServerWorld) world, pos, player)); + return server == null || world.isClient || (world instanceof ServerWorld && !server.isSpawnProtected( (ServerWorld) world, pos, player )); } @Subscribe - public void onTurtleAction(TurtleActionEvent event) { - if (ComputerCraft.turtleDisabledActions.contains(event.getAction())) { - event.setCanceled(true, "Action has been disabled"); + public void onTurtleAction( TurtleActionEvent event ) + { + if( ComputerCraft.turtleDisabledActions.contains( event.getAction() ) ) + { + event.setCanceled( true, "Action has been disabled" ); } } } diff --git a/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java b/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java index 5153367ca..255f2d68b 100644 --- a/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java +++ b/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java @@ -12,11 +12,7 @@ import net.minecraft.item.ItemStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Stream; public final class TurtleUpgrades @@ -32,7 +28,7 @@ public final class TurtleUpgrades { this.upgrade = upgrade; this.id = upgrade.getUpgradeID() - .toString(); + .toString(); // TODO This should be the mod id of the mod the peripheral comes from this.modId = ComputerCraft.MOD_ID; this.enabled = true; @@ -178,4 +174,4 @@ public final class TurtleUpgrades wrappers.remove( upgrade ); needsRebuild = true; } -} \ No newline at end of file +} diff --git a/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java b/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java index 472a6a2f8..41c593766 100644 --- a/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java +++ b/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java @@ -28,7 +28,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; -import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.ScreenHandler; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; diff --git a/src/main/java/dan200/computercraft/shared/command/CommandUtils.java b/src/main/java/dan200/computercraft/shared/command/CommandUtils.java index 375dd4402..d64a7935d 100644 --- a/src/main/java/dan200/computercraft/shared/command/CommandUtils.java +++ b/src/main/java/dan200/computercraft/shared/command/CommandUtils.java @@ -6,56 +6,67 @@ package dan200.computercraft.shared.command; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import dan200.computercraft.api.turtle.FakePlayer; +import net.minecraft.command.CommandSource; +import net.minecraft.entity.Entity; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; + import java.util.Arrays; import java.util.Locale; import java.util.concurrent.CompletableFuture; import java.util.function.Function; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import dan200.computercraft.api.turtle.FakePlayer; - -import net.minecraft.entity.Entity; -import net.minecraft.command.CommandSource; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; - -public final class CommandUtils { +public final class CommandUtils +{ private CommandUtils() {} - public static boolean isPlayer(ServerCommandSource output) { + public static boolean isPlayer( ServerCommandSource output ) + { Entity sender = output.getEntity(); return sender instanceof ServerPlayerEntity && !(sender instanceof FakePlayer) && ((ServerPlayerEntity) sender).networkHandler != null; } - @SuppressWarnings ("unchecked") - public static CompletableFuture suggestOnServer(CommandContext context, SuggestionsBuilder builder, - Function, CompletableFuture> supplier) { + @SuppressWarnings( "unchecked" ) + public static CompletableFuture suggestOnServer( CommandContext context, SuggestionsBuilder builder, + Function, CompletableFuture> supplier ) + { Object source = context.getSource(); - if (!(source instanceof CommandSource)) { + if( !(source instanceof CommandSource) ) + { return Suggestions.empty(); - } else if (source instanceof ServerCommandSource) { - return supplier.apply((CommandContext) context); - } else { - return ((CommandSource) source).getCompletions((CommandContext) context, builder); + } + else if( source instanceof ServerCommandSource ) + { + return supplier.apply( (CommandContext) context ); + } + else + { + return ((CommandSource) source).getCompletions( (CommandContext) context, builder ); } } - public static CompletableFuture suggest(SuggestionsBuilder builder, T[] candidates, Function toString) { - return suggest(builder, Arrays.asList(candidates), toString); + public static CompletableFuture suggest( SuggestionsBuilder builder, T[] candidates, Function toString ) + { + return suggest( builder, Arrays.asList( candidates ), toString ); } - public static CompletableFuture suggest(SuggestionsBuilder builder, Iterable candidates, Function toString) { + public static CompletableFuture suggest( SuggestionsBuilder builder, Iterable candidates, Function toString ) + { String remaining = builder.getRemaining() - .toLowerCase(Locale.ROOT); - for (T choice : candidates) { - String name = toString.apply(choice); - if (!name.toLowerCase(Locale.ROOT) - .startsWith(remaining)) { + .toLowerCase( Locale.ROOT ); + for( T choice : candidates ) + { + String name = toString.apply( choice ); + if( !name.toLowerCase( Locale.ROOT ) + .startsWith( remaining ) ) + { continue; } - builder.suggest(name); + builder.suggest( name ); } return builder.buildFuture(); diff --git a/src/main/java/dan200/computercraft/shared/command/Exceptions.java b/src/main/java/dan200/computercraft/shared/command/Exceptions.java index 2e635b3fe..88f173093 100644 --- a/src/main/java/dan200/computercraft/shared/command/Exceptions.java +++ b/src/main/java/dan200/computercraft/shared/command/Exceptions.java @@ -9,29 +9,32 @@ package dan200.computercraft.shared.command; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; - import net.minecraft.text.TranslatableText; -public final class Exceptions { - public static final DynamicCommandExceptionType COMPUTER_ARG_NONE = translated1("argument.computercraft.computer.no_matching"); - public static final Dynamic2CommandExceptionType COMPUTER_ARG_MANY = translated2("argument.computercraft.computer.many_matching"); +public final class Exceptions +{ + public static final DynamicCommandExceptionType COMPUTER_ARG_NONE = translated1( "argument.computercraft.computer.no_matching" ); + public static final Dynamic2CommandExceptionType COMPUTER_ARG_MANY = translated2( "argument.computercraft.computer.many_matching" ); - public static final DynamicCommandExceptionType TRACKING_FIELD_ARG_NONE = translated1("argument.computercraft.tracking_field.no_field"); - public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated("argument.computercraft.argument_expected"); - static final SimpleCommandExceptionType NOT_TRACKING_EXCEPTION = translated("commands.computercraft.track.stop.not_enabled"); - static final SimpleCommandExceptionType NO_TIMINGS_EXCEPTION = translated("commands.computercraft.track.dump.no_timings"); - static final SimpleCommandExceptionType TP_NOT_THERE = translated("commands.computercraft.tp.not_there"); - static final SimpleCommandExceptionType TP_NOT_PLAYER = translated("commands.computercraft.tp.not_player"); + public static final DynamicCommandExceptionType TRACKING_FIELD_ARG_NONE = translated1( "argument.computercraft.tracking_field.no_field" ); + public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated( "argument.computercraft.argument_expected" ); + static final SimpleCommandExceptionType NOT_TRACKING_EXCEPTION = translated( "commands.computercraft.track.stop.not_enabled" ); + static final SimpleCommandExceptionType NO_TIMINGS_EXCEPTION = translated( "commands.computercraft.track.dump.no_timings" ); + static final SimpleCommandExceptionType TP_NOT_THERE = translated( "commands.computercraft.tp.not_there" ); + static final SimpleCommandExceptionType TP_NOT_PLAYER = translated( "commands.computercraft.tp.not_player" ); - private static SimpleCommandExceptionType translated(String key) { - return new SimpleCommandExceptionType(new TranslatableText(key)); + private static SimpleCommandExceptionType translated( String key ) + { + return new SimpleCommandExceptionType( new TranslatableText( key ) ); } - private static DynamicCommandExceptionType translated1(String key) { - return new DynamicCommandExceptionType(x -> new TranslatableText(key, x)); + private static DynamicCommandExceptionType translated1( String key ) + { + return new DynamicCommandExceptionType( x -> new TranslatableText( key, x ) ); } - private static Dynamic2CommandExceptionType translated2(String key) { - return new Dynamic2CommandExceptionType((x, y) -> new TranslatableText(key, x, y)); + private static Dynamic2CommandExceptionType translated2( String key ) + { + return new Dynamic2CommandExceptionType( ( x, y ) -> new TranslatableText( key, x, y ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentSerializers.java b/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentSerializers.java index cb885e65f..a8520734d 100644 --- a/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentSerializers.java +++ b/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentSerializers.java @@ -8,30 +8,34 @@ package dan200.computercraft.shared.command.arguments; import com.mojang.brigadier.arguments.ArgumentType; import dan200.computercraft.ComputerCraft; - import net.minecraft.command.argument.ArgumentTypes; import net.minecraft.command.argument.serialize.ArgumentSerializer; import net.minecraft.command.argument.serialize.ConstantArgumentSerializer; import net.minecraft.util.Identifier; -public final class ArgumentSerializers { - public static void register() { - register(new Identifier(ComputerCraft.MOD_ID, "tracking_field"), TrackingFieldArgumentType.trackingField()); - register(new Identifier(ComputerCraft.MOD_ID, "computer"), ComputerArgumentType.oneComputer()); - register(new Identifier(ComputerCraft.MOD_ID, "computers"), ComputersArgumentType.class, new ComputersArgumentType.Serializer()); - registerUnsafe(new Identifier(ComputerCraft.MOD_ID, "repeat"), RepeatArgumentType.class, new RepeatArgumentType.Serializer()); +public final class ArgumentSerializers +{ + public static void register() + { + register( new Identifier( ComputerCraft.MOD_ID, "tracking_field" ), TrackingFieldArgumentType.trackingField() ); + register( new Identifier( ComputerCraft.MOD_ID, "computer" ), ComputerArgumentType.oneComputer() ); + register( new Identifier( ComputerCraft.MOD_ID, "computers" ), ComputersArgumentType.class, new ComputersArgumentType.Serializer() ); + registerUnsafe( new Identifier( ComputerCraft.MOD_ID, "repeat" ), RepeatArgumentType.class, new RepeatArgumentType.Serializer() ); } - private static > void register(Identifier id, T instance) { - registerUnsafe(id, instance.getClass(), new ConstantArgumentSerializer<>(() -> instance)); + private static > void register( Identifier id, T instance ) + { + registerUnsafe( id, instance.getClass(), new ConstantArgumentSerializer<>( () -> instance ) ); } - private static > void register(Identifier id, Class type, ArgumentSerializer serializer) { - ArgumentTypes.register(id.toString(), type, serializer); + private static > void register( Identifier id, Class type, ArgumentSerializer serializer ) + { + ArgumentTypes.register( id.toString(), type, serializer ); } - @SuppressWarnings ("unchecked") - private static > void registerUnsafe(Identifier id, Class type, ArgumentSerializer serializer) { - ArgumentTypes.register(id.toString(), type, (ArgumentSerializer) serializer); + @SuppressWarnings( "unchecked" ) + private static > void registerUnsafe( Identifier id, Class type, ArgumentSerializer serializer ) + { + ArgumentTypes.register( id.toString(), type, (ArgumentSerializer) serializer ); } } diff --git a/src/main/java/dan200/computercraft/shared/command/arguments/ChoiceArgumentType.java b/src/main/java/dan200/computercraft/shared/command/arguments/ChoiceArgumentType.java index f2da90763..aa6e48fea 100644 --- a/src/main/java/dan200/computercraft/shared/command/arguments/ChoiceArgumentType.java +++ b/src/main/java/dan200/computercraft/shared/command/arguments/ChoiceArgumentType.java @@ -6,14 +6,6 @@ package dan200.computercraft.shared.command.arguments; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; - import com.mojang.brigadier.Message; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; @@ -23,13 +15,19 @@ import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -public abstract class ChoiceArgumentType implements ArgumentType { +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +public abstract class ChoiceArgumentType implements ArgumentType +{ private final Iterable choices; private final Function name; private final Function tooltip; private final DynamicCommandExceptionType exception; - protected ChoiceArgumentType(Iterable choices, Function name, Function tooltip, DynamicCommandExceptionType exception) { + protected ChoiceArgumentType( Iterable choices, Function name, Function tooltip, DynamicCommandExceptionType exception ) + { this.choices = choices; this.name = name; this.tooltip = tooltip; @@ -37,44 +35,52 @@ public abstract class ChoiceArgumentType implements ArgumentType { } @Override - public T parse(StringReader reader) throws CommandSyntaxException { + public T parse( StringReader reader ) throws CommandSyntaxException + { int start = reader.getCursor(); String name = reader.readUnquotedString(); - for (T choice : this.choices) { - String choiceName = this.name.apply(choice); - if (name.equals(choiceName)) { + for( T choice : this.choices ) + { + String choiceName = this.name.apply( choice ); + if( name.equals( choiceName ) ) + { return choice; } } - reader.setCursor(start); - throw this.exception.createWithContext(reader, name); + reader.setCursor( start ); + throw this.exception.createWithContext( reader, name ); } @Override - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) + { String remaining = builder.getRemaining() - .toLowerCase(Locale.ROOT); - for (T choice : this.choices) { - String name = this.name.apply(choice); - if (!name.toLowerCase(Locale.ROOT) - .startsWith(remaining)) { + .toLowerCase( Locale.ROOT ); + for( T choice : this.choices ) + { + String name = this.name.apply( choice ); + if( !name.toLowerCase( Locale.ROOT ) + .startsWith( remaining ) ) + { continue; } - builder.suggest(name, this.tooltip.apply(choice)); + builder.suggest( name, this.tooltip.apply( choice ) ); } return builder.buildFuture(); } @Override - public Collection getExamples() { - List items = this.choices instanceof Collection ? new ArrayList<>(((Collection) this.choices).size()) : new ArrayList<>(); - for (T choice : this.choices) { - items.add(this.name.apply(choice)); + public Collection getExamples() + { + List items = this.choices instanceof Collection ? new ArrayList<>( ((Collection) this.choices).size() ) : new ArrayList<>(); + for( T choice : this.choices ) + { + items.add( this.name.apply( choice ) ); } - items.sort(Comparator.naturalOrder()); + items.sort( Comparator.naturalOrder() ); return items; } } diff --git a/src/main/java/dan200/computercraft/shared/command/arguments/ComputerArgumentType.java b/src/main/java/dan200/computercraft/shared/command/arguments/ComputerArgumentType.java index b7f53fabf..06840b154 100644 --- a/src/main/java/dan200/computercraft/shared/command/arguments/ComputerArgumentType.java +++ b/src/main/java/dan200/computercraft/shared/command/arguments/ComputerArgumentType.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.command.arguments; -import static dan200.computercraft.shared.command.Exceptions.COMPUTER_ARG_MANY; - -import java.util.Collection; -import java.util.concurrent.CompletableFuture; - import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; @@ -19,73 +14,90 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import dan200.computercraft.shared.command.arguments.ComputersArgumentType.ComputersSupplier; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.server.command.ServerCommandSource; -public final class ComputerArgumentType implements ArgumentType { +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +import static dan200.computercraft.shared.command.Exceptions.COMPUTER_ARG_MANY; + +public final class ComputerArgumentType implements ArgumentType +{ private static final ComputerArgumentType INSTANCE = new ComputerArgumentType(); - private ComputerArgumentType() { + private ComputerArgumentType() + { } - public static ComputerArgumentType oneComputer() { + public static ComputerArgumentType oneComputer() + { return INSTANCE; } - public static ServerComputer getComputerArgument(CommandContext context, String name) throws CommandSyntaxException { - return context.getArgument(name, ComputerSupplier.class) - .unwrap(context.getSource()); + public static ServerComputer getComputerArgument( CommandContext context, String name ) throws CommandSyntaxException + { + return context.getArgument( name, ComputerSupplier.class ) + .unwrap( context.getSource() ); } @Override - public ComputerSupplier parse(StringReader reader) throws CommandSyntaxException { + public ComputerSupplier parse( StringReader reader ) throws CommandSyntaxException + { int start = reader.getCursor(); ComputersSupplier supplier = ComputersArgumentType.someComputers() - .parse(reader); + .parse( reader ); String selector = reader.getString() - .substring(start, reader.getCursor()); + .substring( start, reader.getCursor() ); return s -> { - Collection computers = supplier.unwrap(s); + Collection computers = supplier.unwrap( s ); - if (computers.size() == 1) { + if( computers.size() == 1 ) + { return computers.iterator() - .next(); + .next(); } StringBuilder builder = new StringBuilder(); boolean first = true; - for (ServerComputer computer : computers) { - if (first) { + for( ServerComputer computer : computers ) + { + if( first ) + { first = false; - } else { - builder.append(", "); + } + else + { + builder.append( ", " ); } - builder.append(computer.getInstanceID()); + builder.append( computer.getInstanceID() ); } // We have an incorrect number of computers: reset and throw an error - reader.setCursor(start); - throw COMPUTER_ARG_MANY.createWithContext(reader, selector, builder.toString()); + reader.setCursor( start ); + throw COMPUTER_ARG_MANY.createWithContext( reader, selector, builder.toString() ); }; } @Override - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) + { return ComputersArgumentType.someComputers() - .listSuggestions(context, builder); + .listSuggestions( context, builder ); } @Override - public Collection getExamples() { + public Collection getExamples() + { return ComputersArgumentType.someComputers() - .getExamples(); + .getExamples(); } @FunctionalInterface - public interface ComputerSupplier { - ServerComputer unwrap(ServerCommandSource source) throws CommandSyntaxException; + public interface ComputerSupplier + { + ServerComputer unwrap( ServerCommandSource source ) throws CommandSyntaxException; } } diff --git a/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java b/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java index efce72ec0..e69ae8558 100644 --- a/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java +++ b/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java @@ -6,25 +6,6 @@ package dan200.computercraft.shared.command.arguments; -import static dan200.computercraft.shared.command.CommandUtils.suggest; -import static dan200.computercraft.shared.command.CommandUtils.suggestOnServer; -import static dan200.computercraft.shared.command.Exceptions.COMPUTER_ARG_NONE; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import javax.annotation.Nonnull; - import com.google.gson.JsonObject; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; @@ -35,155 +16,201 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder; import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.command.argument.serialize.ArgumentSerializer; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.command.ServerCommandSource; -public final class ComputersArgumentType implements ArgumentType { - private static final ComputersArgumentType MANY = new ComputersArgumentType(false); - private static final ComputersArgumentType SOME = new ComputersArgumentType(true); +import javax.annotation.Nonnull; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; - private static final List EXAMPLES = Arrays.asList("0", "#0", "@Label", "~Advanced"); +import static dan200.computercraft.shared.command.CommandUtils.suggest; +import static dan200.computercraft.shared.command.CommandUtils.suggestOnServer; +import static dan200.computercraft.shared.command.Exceptions.COMPUTER_ARG_NONE; + +public final class ComputersArgumentType implements ArgumentType +{ + private static final ComputersArgumentType MANY = new ComputersArgumentType( false ); + private static final ComputersArgumentType SOME = new ComputersArgumentType( true ); + + private static final List EXAMPLES = Arrays.asList( "0", "#0", "@Label", "~Advanced" ); private final boolean requireSome; - private ComputersArgumentType(boolean requireSome) { + private ComputersArgumentType( boolean requireSome ) + { this.requireSome = requireSome; } - public static ComputersArgumentType manyComputers() { + public static ComputersArgumentType manyComputers() + { return MANY; } - public static ComputersArgumentType someComputers() { + public static ComputersArgumentType someComputers() + { return SOME; } - public static Collection getComputersArgument(CommandContext context, String name) throws CommandSyntaxException { - return context.getArgument(name, ComputersSupplier.class) - .unwrap(context.getSource()); + public static Collection getComputersArgument( CommandContext context, String name ) throws CommandSyntaxException + { + return context.getArgument( name, ComputersSupplier.class ) + .unwrap( context.getSource() ); } - public static Set unwrap(ServerCommandSource source, Collection suppliers) throws CommandSyntaxException { + public static Set unwrap( ServerCommandSource source, Collection suppliers ) throws CommandSyntaxException + { Set computers = new HashSet<>(); - for (ComputersSupplier supplier : suppliers) { - computers.addAll(supplier.unwrap(source)); + for( ComputersSupplier supplier : suppliers ) + { + computers.addAll( supplier.unwrap( source ) ); } return computers; } @Override - public ComputersSupplier parse(StringReader reader) throws CommandSyntaxException { + public ComputersSupplier parse( StringReader reader ) throws CommandSyntaxException + { int start = reader.getCursor(); char kind = reader.peek(); ComputersSupplier computers; - if (kind == '@') { + if( kind == '@' ) + { reader.skip(); String label = reader.readUnquotedString(); - computers = getComputers(x -> Objects.equals(label, x.getLabel())); - } else if (kind == '~') { + computers = getComputers( x -> Objects.equals( label, x.getLabel() ) ); + } + else if( kind == '~' ) + { reader.skip(); String family = reader.readUnquotedString(); - computers = getComputers(x -> x.getFamily() - .name() - .equalsIgnoreCase(family)); - } else if (kind == '#') { + computers = getComputers( x -> x.getFamily() + .name() + .equalsIgnoreCase( family ) ); + } + else if( kind == '#' ) + { reader.skip(); int id = reader.readInt(); - computers = getComputers(x -> x.getID() == id); - } else { + computers = getComputers( x -> x.getID() == id ); + } + else + { int instance = reader.readInt(); computers = s -> { - ServerComputer computer = ComputerCraft.serverComputerRegistry.get(instance); - return computer == null ? Collections.emptyList() : Collections.singletonList(computer); + ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instance ); + return computer == null ? Collections.emptyList() : Collections.singletonList( computer ); }; } - if (this.requireSome) { + if( this.requireSome ) + { String selector = reader.getString() - .substring(start, reader.getCursor()); + .substring( start, reader.getCursor() ); return source -> { - Collection matched = computers.unwrap(source); - if (matched.isEmpty()) { - throw COMPUTER_ARG_NONE.create(selector); + Collection matched = computers.unwrap( source ); + if( matched.isEmpty() ) + { + throw COMPUTER_ARG_NONE.create( selector ); } return matched; }; - } else { + } + else + { return computers; } } @Override - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) + { String remaining = builder.getRemaining(); // We can run this one on the client, for obvious reasons. - if (remaining.startsWith("~")) { - return suggest(builder, ComputerFamily.values(), x -> "~" + x.name()); + if( remaining.startsWith( "~" ) ) + { + return suggest( builder, ComputerFamily.values(), x -> "~" + x.name() ); } // Verify we've a command source and we're running on the server - return suggestOnServer(context, builder, s -> { - if (remaining.startsWith("@")) { - suggestComputers(builder, remaining, x -> { + return suggestOnServer( context, builder, s -> { + if( remaining.startsWith( "@" ) ) + { + suggestComputers( builder, remaining, x -> { String label = x.getLabel(); return label == null ? null : "@" + label; - }); - } else if (remaining.startsWith("#")) { - suggestComputers(builder, remaining, c -> "#" + c.getID()); - } else { - suggestComputers(builder, remaining, c -> Integer.toString(c.getInstanceID())); + } ); + } + else if( remaining.startsWith( "#" ) ) + { + suggestComputers( builder, remaining, c -> "#" + c.getID() ); + } + else + { + suggestComputers( builder, remaining, c -> Integer.toString( c.getInstanceID() ) ); } return builder.buildFuture(); - }); + } ); } @Override - public Collection getExamples() { + public Collection getExamples() + { return EXAMPLES; } - private static void suggestComputers(SuggestionsBuilder builder, String remaining, Function renderer) { - remaining = remaining.toLowerCase(Locale.ROOT); - for (ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers()) { - String converted = renderer.apply(computer); - if (converted != null && converted.toLowerCase(Locale.ROOT) - .startsWith(remaining)) { - builder.suggest(converted); + private static void suggestComputers( SuggestionsBuilder builder, String remaining, Function renderer ) + { + remaining = remaining.toLowerCase( Locale.ROOT ); + for( ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers() ) + { + String converted = renderer.apply( computer ); + if( converted != null && converted.toLowerCase( Locale.ROOT ) + .startsWith( remaining ) ) + { + builder.suggest( converted ); } } } - private static ComputersSupplier getComputers(Predicate predicate) { - return s -> Collections.unmodifiableList(ComputerCraft.serverComputerRegistry.getComputers() - .stream() - .filter(predicate) - .collect(Collectors.toList())); + private static ComputersSupplier getComputers( Predicate predicate ) + { + return s -> Collections.unmodifiableList( ComputerCraft.serverComputerRegistry.getComputers() + .stream() + .filter( predicate ) + .collect( Collectors.toList() ) ); } @FunctionalInterface - public interface ComputersSupplier { - Collection unwrap(ServerCommandSource source) throws CommandSyntaxException; + public interface ComputersSupplier + { + Collection unwrap( ServerCommandSource source ) throws CommandSyntaxException; } - public static class Serializer implements ArgumentSerializer { + public static class Serializer implements ArgumentSerializer + { @Override - public void toPacket(@Nonnull ComputersArgumentType arg, @Nonnull PacketByteBuf buf) { - buf.writeBoolean(arg.requireSome); + public void toPacket( @Nonnull ComputersArgumentType arg, @Nonnull PacketByteBuf buf ) + { + buf.writeBoolean( arg.requireSome ); } @Nonnull @Override - public ComputersArgumentType fromPacket(@Nonnull PacketByteBuf buf) { + public ComputersArgumentType fromPacket( @Nonnull PacketByteBuf buf ) + { return buf.readBoolean() ? SOME : MANY; } @Override - public void toJson(@Nonnull ComputersArgumentType arg, @Nonnull JsonObject json) { - json.addProperty("requireSome", arg.requireSome); + public void toJson( @Nonnull ComputersArgumentType arg, @Nonnull JsonObject json ) + { + json.addProperty( "requireSome", arg.requireSome ); } } } diff --git a/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java b/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java index 36a6f1009..6f6ac8931 100644 --- a/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java +++ b/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java @@ -6,15 +6,6 @@ package dan200.computercraft.shared.command.arguments; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.function.BiConsumer; - -import javax.annotation.Nonnull; - import com.google.gson.JsonObject; import com.mojang.brigadier.Message; import com.mojang.brigadier.StringReader; @@ -24,13 +15,20 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; - import net.minecraft.command.argument.ArgumentTypes; import net.minecraft.command.argument.serialize.ArgumentSerializer; import net.minecraft.network.PacketByteBuf; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; + /** * Reads one argument multiple times. * @@ -42,13 +40,15 @@ import net.minecraft.text.Text; * @param The type of each value returned * @param The type of the inner parser. This will normally be a {@link List} or {@code T}. */ -public final class RepeatArgumentType implements ArgumentType> { +public final class RepeatArgumentType implements ArgumentType> +{ private final ArgumentType child; private final BiConsumer, U> appender; private final boolean flatten; private final SimpleCommandExceptionType some; - private RepeatArgumentType(ArgumentType child, BiConsumer, U> appender, boolean flatten, SimpleCommandExceptionType some) { + private RepeatArgumentType( ArgumentType child, BiConsumer, U> appender, boolean flatten, SimpleCommandExceptionType some ) + { this.child = child; this.appender = appender; this.flatten = flatten; @@ -60,104 +60,123 @@ public final class RepeatArgumentType implements ArgumentType> { return new RepeatArgumentType<>( appender, List::add, false, missing ); } - public static RepeatArgumentType> someFlat(ArgumentType> appender, SimpleCommandExceptionType missing) { - return new RepeatArgumentType<>(appender, List::addAll, true, missing); + public static RepeatArgumentType> someFlat( ArgumentType> appender, SimpleCommandExceptionType missing ) + { + return new RepeatArgumentType<>( appender, List::addAll, true, missing ); } @Override - public List parse(StringReader reader) throws CommandSyntaxException { + public List parse( StringReader reader ) throws CommandSyntaxException + { boolean hadSome = false; List out = new ArrayList<>(); - while (true) { + while( true ) + { reader.skipWhitespace(); - if (!reader.canRead()) { + if( !reader.canRead() ) + { break; } int startParse = reader.getCursor(); - this.appender.accept(out, this.child.parse(reader)); + this.appender.accept( out, this.child.parse( reader ) ); hadSome = true; - if (reader.getCursor() == startParse) { - throw new IllegalStateException(this.child + " did not consume any input on " + reader.getRemaining()); + if( reader.getCursor() == startParse ) + { + throw new IllegalStateException( this.child + " did not consume any input on " + reader.getRemaining() ); } } // Note that each child may return an empty list, we just require that some actual input // was consumed. // We should probably review that this is sensible in the future. - if (!hadSome) { - throw this.some.createWithContext(reader); + if( !hadSome ) + { + throw this.some.createWithContext( reader ); } - return Collections.unmodifiableList(out); + return Collections.unmodifiableList( out ); } @Override - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - StringReader reader = new StringReader(builder.getInput()); - reader.setCursor(builder.getStart()); + public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) + { + StringReader reader = new StringReader( builder.getInput() ); + reader.setCursor( builder.getStart() ); int previous = reader.getCursor(); - while (reader.canRead()) { - try { - this.child.parse(reader); - } catch (CommandSyntaxException e) { + while( reader.canRead() ) + { + try + { + this.child.parse( reader ); + } + catch( CommandSyntaxException e ) + { break; } int cursor = reader.getCursor(); reader.skipWhitespace(); - if (cursor == reader.getCursor()) { + if( cursor == reader.getCursor() ) + { break; } previous = reader.getCursor(); } - reader.setCursor(previous); - return this.child.listSuggestions(context, builder.createOffset(previous)); + reader.setCursor( previous ); + return this.child.listSuggestions( context, builder.createOffset( previous ) ); } @Override - public Collection getExamples() { + public Collection getExamples() + { return this.child.getExamples(); } - public static class Serializer implements ArgumentSerializer> { + public static class Serializer implements ArgumentSerializer> + { @Override - public void toPacket(@Nonnull RepeatArgumentType arg, @Nonnull PacketByteBuf buf) { - buf.writeBoolean(arg.flatten); - ArgumentTypes.toPacket(buf, arg.child); - buf.writeText(getMessage(arg)); + public void toPacket( @Nonnull RepeatArgumentType arg, @Nonnull PacketByteBuf buf ) + { + buf.writeBoolean( arg.flatten ); + ArgumentTypes.toPacket( buf, arg.child ); + buf.writeText( getMessage( arg ) ); } @Nonnull @Override - @SuppressWarnings ({ + @SuppressWarnings( { "unchecked", "rawtypes" - }) - public RepeatArgumentType fromPacket(@Nonnull PacketByteBuf buf) { + } ) + public RepeatArgumentType fromPacket( @Nonnull PacketByteBuf buf ) + { boolean isList = buf.readBoolean(); - ArgumentType child = ArgumentTypes.fromPacket(buf); + ArgumentType child = ArgumentTypes.fromPacket( buf ); Text message = buf.readText(); - BiConsumer, ?> appender = isList ? (list, x) -> list.addAll((Collection) x) : List::add; - return new RepeatArgumentType(child, appender, isList, new SimpleCommandExceptionType(message)); + BiConsumer, ?> appender = isList ? ( list, x ) -> list.addAll( (Collection) x ) : List::add; + return new RepeatArgumentType( child, appender, isList, new SimpleCommandExceptionType( message ) ); } @Override - public void toJson(@Nonnull RepeatArgumentType arg, @Nonnull JsonObject json) { - json.addProperty("flatten", arg.flatten); - json.addProperty("child", "<>"); // TODO: Potentially serialize this using reflection. - json.addProperty("error", Text.Serializer.toJson(getMessage(arg))); + public void toJson( @Nonnull RepeatArgumentType arg, @Nonnull JsonObject json ) + { + json.addProperty( "flatten", arg.flatten ); + json.addProperty( "child", "<>" ); // TODO: Potentially serialize this using reflection. + json.addProperty( "error", Text.Serializer.toJson( getMessage( arg ) ) ); } - private static Text getMessage(RepeatArgumentType arg) { + private static Text getMessage( RepeatArgumentType arg ) + { Message message = arg.some.create() - .getRawMessage(); - if (message instanceof Text) { + .getRawMessage(); + if( message instanceof Text ) + { return (Text) message; } - return new LiteralText(message.getString()); + return new LiteralText( message.getString() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/command/arguments/TrackingFieldArgumentType.java b/src/main/java/dan200/computercraft/shared/command/arguments/TrackingFieldArgumentType.java index 5f529ebf6..06f2330fd 100644 --- a/src/main/java/dan200/computercraft/shared/command/arguments/TrackingFieldArgumentType.java +++ b/src/main/java/dan200/computercraft/shared/command/arguments/TrackingFieldArgumentType.java @@ -6,20 +6,23 @@ package dan200.computercraft.shared.command.arguments; -import static dan200.computercraft.shared.command.text.ChatHelpers.translate; - import dan200.computercraft.core.tracking.TrackingField; import dan200.computercraft.shared.command.Exceptions; -public final class TrackingFieldArgumentType extends ChoiceArgumentType { +import static dan200.computercraft.shared.command.text.ChatHelpers.translate; + +public final class TrackingFieldArgumentType extends ChoiceArgumentType +{ private static final TrackingFieldArgumentType INSTANCE = new TrackingFieldArgumentType(); - private TrackingFieldArgumentType() { - super(TrackingField.fields() - .values(), TrackingField::id, x -> translate(x.translationKey()), Exceptions.TRACKING_FIELD_ARG_NONE); + private TrackingFieldArgumentType() + { + super( TrackingField.fields() + .values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE ); } - public static TrackingFieldArgumentType trackingField() { + public static TrackingFieldArgumentType trackingField() + { return INSTANCE; } } diff --git a/src/main/java/dan200/computercraft/shared/command/builder/ArgCommand.java b/src/main/java/dan200/computercraft/shared/command/builder/ArgCommand.java index 58f190ca2..ea834c4c8 100644 --- a/src/main/java/dan200/computercraft/shared/command/builder/ArgCommand.java +++ b/src/main/java/dan200/computercraft/shared/command/builder/ArgCommand.java @@ -17,6 +17,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; * @param The argument given to this command when executed. */ @FunctionalInterface -public interface ArgCommand { - int run(CommandContext ctx, T arg) throws CommandSyntaxException; +public interface ArgCommand +{ + int run( CommandContext ctx, T arg ) throws CommandSyntaxException; } diff --git a/src/main/java/dan200/computercraft/shared/command/builder/CommandBuilder.java b/src/main/java/dan200/computercraft/shared/command/builder/CommandBuilder.java index 8191f43ca..901e97eb3 100644 --- a/src/main/java/dan200/computercraft/shared/command/builder/CommandBuilder.java +++ b/src/main/java/dan200/computercraft/shared/command/builder/CommandBuilder.java @@ -6,15 +6,6 @@ package dan200.computercraft.shared.command.builder; -import static dan200.computercraft.shared.command.Exceptions.ARGUMENT_EXPECTED; -import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.literal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; -import java.util.function.Supplier; - import com.mojang.brigadier.Command; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.builder.ArgumentBuilder; @@ -22,100 +13,126 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.tree.CommandNode; import dan200.computercraft.shared.command.arguments.RepeatArgumentType; - import net.minecraft.server.command.ServerCommandSource; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import static dan200.computercraft.shared.command.Exceptions.ARGUMENT_EXPECTED; +import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.literal; + /** * An alternative way of building command nodes, so one does not have to nest. {@link ArgumentBuilder#then(CommandNode)}s. * * @param The command source we consume. */ -public class CommandBuilder implements CommandNodeBuilder> { +public class CommandBuilder implements CommandNodeBuilder> +{ private List> args = new ArrayList<>(); private Predicate requires; - public static CommandBuilder args() { + public static CommandBuilder args() + { return new CommandBuilder<>(); } - public static CommandBuilder command(String literal) { + public static CommandBuilder command( String literal ) + { CommandBuilder builder = new CommandBuilder<>(); - builder.args.add(literal(literal)); + builder.args.add( literal( literal ) ); return builder; } - public CommandBuilder requires(Predicate predicate) { - this.requires = this.requires == null ? predicate : this.requires.and(predicate); + public CommandBuilder requires( Predicate predicate ) + { + this.requires = this.requires == null ? predicate : this.requires.and( predicate ); return this; } - public CommandBuilder arg(String name, ArgumentType type) { - this.args.add(RequiredArgumentBuilder.argument(name, type)); + public CommandBuilder arg( String name, ArgumentType type ) + { + this.args.add( RequiredArgumentBuilder.argument( name, type ) ); return this; } - public CommandNodeBuilder>> argManyValue(String name, ArgumentType type, T defaultValue) { - return this.argManyValue(name, type, Collections.singletonList(defaultValue)); + public CommandNodeBuilder>> argManyValue( String name, ArgumentType type, T defaultValue ) + { + return this.argManyValue( name, type, Collections.singletonList( defaultValue ) ); } - public CommandNodeBuilder>> argManyValue(String name, ArgumentType type, List empty) { - return this.argMany(name, type, () -> empty); + public CommandNodeBuilder>> argManyValue( String name, ArgumentType type, List empty ) + { + return this.argMany( name, type, () -> empty ); } - public CommandNodeBuilder>> argMany(String name, ArgumentType type, Supplier> empty) { - return this.argMany(name, RepeatArgumentType.some(type, ARGUMENT_EXPECTED), empty); + public CommandNodeBuilder>> argMany( String name, ArgumentType type, Supplier> empty ) + { + return this.argMany( name, RepeatArgumentType.some( type, ARGUMENT_EXPECTED ), empty ); } - private CommandNodeBuilder>> argMany(String name, RepeatArgumentType type, Supplier> empty) { - if (this.args.isEmpty()) { - throw new IllegalStateException("Cannot have empty arg chain builder"); + private CommandNodeBuilder>> argMany( String name, RepeatArgumentType type, Supplier> empty ) + { + if( this.args.isEmpty() ) + { + throw new IllegalStateException( "Cannot have empty arg chain builder" ); } return command -> { // The node for no arguments - ArgumentBuilder tail = this.tail(ctx -> command.run(ctx, empty.get())); + ArgumentBuilder tail = this.tail( ctx -> command.run( ctx, empty.get() ) ); // The node for one or more arguments - ArgumentBuilder moreArg = RequiredArgumentBuilder.>argument(name, type).executes(ctx -> command.run(ctx, getList(ctx, name))); + ArgumentBuilder moreArg = RequiredArgumentBuilder.>argument( name, type ).executes( ctx -> command.run( ctx, getList( ctx, name ) ) ); // Chain all of them together! - tail.then(moreArg); - return this.link(tail); + tail.then( moreArg ); + return this.link( tail ); }; } - private ArgumentBuilder tail(Command command) { - ArgumentBuilder defaultTail = this.args.get(this.args.size() - 1); - defaultTail.executes(command); - if (this.requires != null) { - defaultTail.requires(this.requires); + private ArgumentBuilder tail( Command command ) + { + ArgumentBuilder defaultTail = this.args.get( this.args.size() - 1 ); + defaultTail.executes( command ); + if( this.requires != null ) + { + defaultTail.requires( this.requires ); } return defaultTail; } - @SuppressWarnings ("unchecked") - private static List getList(CommandContext context, String name) { - return (List) context.getArgument(name, List.class); + @SuppressWarnings( "unchecked" ) + private static List getList( CommandContext context, String name ) + { + return (List) context.getArgument( name, List.class ); } - private CommandNode link(ArgumentBuilder tail) { - for (int i = this.args.size() - 2; i >= 0; i--) { - tail = this.args.get(i) - .then(tail); + private CommandNode link( ArgumentBuilder tail ) + { + for( int i = this.args.size() - 2; i >= 0; i-- ) + { + tail = this.args.get( i ) + .then( tail ); } return tail.build(); } - public CommandNodeBuilder>> argManyFlatten(String name, ArgumentType> type, Supplier> empty) { - return this.argMany(name, RepeatArgumentType.someFlat(type, ARGUMENT_EXPECTED), empty); + public CommandNodeBuilder>> argManyFlatten( String name, ArgumentType> type, Supplier> empty ) + { + return this.argMany( name, RepeatArgumentType.someFlat( type, ARGUMENT_EXPECTED ), empty ); } @Override - public CommandNode executes(Command command) { - if (this.args.isEmpty()) { - throw new IllegalStateException("Cannot have empty arg chain builder"); + public CommandNode executes( Command command ) + { + if( this.args.isEmpty() ) + { + throw new IllegalStateException( "Cannot have empty arg chain builder" ); } - return this.link(this.tail(command)); + return this.link( this.tail( command ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/command/builder/CommandNodeBuilder.java b/src/main/java/dan200/computercraft/shared/command/builder/CommandNodeBuilder.java index 765dcca2d..dc10a5eea 100644 --- a/src/main/java/dan200/computercraft/shared/command/builder/CommandNodeBuilder.java +++ b/src/main/java/dan200/computercraft/shared/command/builder/CommandNodeBuilder.java @@ -15,12 +15,13 @@ import com.mojang.brigadier.tree.CommandNode; * @param The type of action to execute when this command is run. */ @FunctionalInterface -public interface CommandNodeBuilder { +public interface CommandNodeBuilder +{ /** * Generate a command node which executes this command. * * @param command The command to run * @return The constructed node. */ - CommandNode executes(T command); + CommandNode executes( T command ); } diff --git a/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java b/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java index 1d728d9f1..58767e62d 100644 --- a/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java +++ b/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java @@ -6,14 +6,6 @@ package dan200.computercraft.shared.command.builder; -import static dan200.computercraft.shared.command.text.ChatHelpers.coloured; -import static dan200.computercraft.shared.command.text.ChatHelpers.translate; - -import java.util.ArrayList; -import java.util.Collection; - -import javax.annotation.Nonnull; - import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.ArgumentBuilder; @@ -21,7 +13,6 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; - import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.ClickEvent; import net.minecraft.text.LiteralText; @@ -29,169 +20,201 @@ import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Collection; + +import static dan200.computercraft.shared.command.text.ChatHelpers.coloured; +import static dan200.computercraft.shared.command.text.ChatHelpers.translate; + /** * An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults to that command when no arguments are * given. */ -public final class HelpingArgumentBuilder extends LiteralArgumentBuilder { +public final class HelpingArgumentBuilder extends LiteralArgumentBuilder +{ private static final Formatting HEADER = Formatting.LIGHT_PURPLE; private static final Formatting SYNOPSIS = Formatting.AQUA; private static final Formatting NAME = Formatting.GREEN; private final Collection children = new ArrayList<>(); - private HelpingArgumentBuilder(String literal) { - super(literal); + private HelpingArgumentBuilder( String literal ) + { + super( literal ); } - public static HelpingArgumentBuilder choice(String literal) { - return new HelpingArgumentBuilder(literal); + public static HelpingArgumentBuilder choice( String literal ) + { + return new HelpingArgumentBuilder( literal ); } - private static Command helpForChild(CommandNode node, String id, String command) { + private static Command helpForChild( CommandNode node, String id, String command ) + { return context -> { context.getSource() - .sendFeedback(getHelp(context, - node, - id + "." + node.getName() - .replace('-', '_'), - command + " " + node.getName()), false); + .sendFeedback( getHelp( context, + node, + id + "." + node.getName() + .replace( '-', '_' ), + command + " " + node.getName() ), false ); return 0; }; } - private static Text getHelp(CommandContext context, CommandNode node, String id, String command) { + private static Text getHelp( CommandContext context, CommandNode node, String id, String command ) + { // An ugly hack to extract usage information from the dispatcher. We generate a temporary node, generate // the shorthand usage, and emit that. CommandDispatcher dispatcher = context.getSource() - .getMinecraftServer() - .getCommandManager() - .getDispatcher(); - CommandNode temp = new LiteralCommandNode<>("_", null, x -> true, null, null, false); - temp.addChild(node); - String usage = dispatcher.getSmartUsage(temp, context.getSource()) - .get(node) - .substring(node.getName() - .length()); + .getMinecraftServer() + .getCommandManager() + .getDispatcher(); + CommandNode temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false ); + temp.addChild( node ); + String usage = dispatcher.getSmartUsage( temp, context.getSource() ) + .get( node ) + .substring( node.getName() + .length() ); - MutableText output = new LiteralText("").append(coloured("/" + command + usage, HEADER)) - .append(" ") - .append(coloured(translate("commands." + id + ".synopsis"), SYNOPSIS)) - .append("\n") - .append(translate("commands." + id + ".desc")); + MutableText output = new LiteralText( "" ).append( coloured( "/" + command + usage, HEADER ) ) + .append( " " ) + .append( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) ) + .append( "\n" ) + .append( translate( "commands." + id + ".desc" ) ); - for (CommandNode child : node.getChildren()) { - if (!child.getRequirement() - .test(context.getSource()) || !(child instanceof LiteralCommandNode)) { + for( CommandNode child : node.getChildren() ) + { + if( !child.getRequirement() + .test( context.getSource() ) || !(child instanceof LiteralCommandNode) ) + { continue; } - output.append("\n"); + output.append( "\n" ); - MutableText component = coloured(child.getName(), NAME); + MutableText component = coloured( child.getName(), NAME ); component.getStyle() - .withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " + child.getName())); - output.append(component); + .withClickEvent( new ClickEvent( ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " + child.getName() ) ); + output.append( component ); - output.append(" - ") - .append(translate("commands." + id + "." + child.getName() + ".synopsis")); + output.append( " - " ) + .append( translate( "commands." + id + "." + child.getName() + ".synopsis" ) ); } return output; } @Override - public LiteralArgumentBuilder then(final ArgumentBuilder argument) { - if (this.getRedirect() != null) { - throw new IllegalStateException("Cannot add children to a redirected node"); + public LiteralArgumentBuilder then( final ArgumentBuilder argument ) + { + if( this.getRedirect() != null ) + { + throw new IllegalStateException( "Cannot add children to a redirected node" ); } - if (argument instanceof HelpingArgumentBuilder) { - this.children.add((HelpingArgumentBuilder) argument); - } else if (argument instanceof LiteralArgumentBuilder) { - super.then(argument); - } else { - throw new IllegalStateException("HelpingArgumentBuilder can only accept literal children"); + if( argument instanceof HelpingArgumentBuilder ) + { + this.children.add( (HelpingArgumentBuilder) argument ); + } + else if( argument instanceof LiteralArgumentBuilder ) + { + super.then( argument ); + } + else + { + throw new IllegalStateException( "HelpingArgumentBuilder can only accept literal children" ); } return this; } @Override - public LiteralArgumentBuilder then(CommandNode argument) { - if (!(argument instanceof LiteralCommandNode)) { - throw new IllegalStateException("HelpingArgumentBuilder can only accept literal children"); + public LiteralArgumentBuilder then( CommandNode argument ) + { + if( !(argument instanceof LiteralCommandNode) ) + { + throw new IllegalStateException( "HelpingArgumentBuilder can only accept literal children" ); } - return super.then(argument); + return super.then( argument ); } @Override - public LiteralArgumentBuilder executes(final Command command) { - throw new IllegalStateException("Cannot use executes on a HelpingArgumentBuilder"); + public LiteralArgumentBuilder executes( final Command command ) + { + throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" ); } @Override - public LiteralCommandNode build() { - return this.buildImpl(this.getLiteral().replace('-', '_'), this.getLiteral()); + public LiteralCommandNode build() + { + return this.buildImpl( this.getLiteral().replace( '-', '_' ), this.getLiteral() ); } - private LiteralCommandNode build(@Nonnull String id, @Nonnull String command) { - return this.buildImpl(id + "." + this.getLiteral().replace('-', '_'), command + " " + this.getLiteral()); + private LiteralCommandNode build( @Nonnull String id, @Nonnull String command ) + { + return this.buildImpl( id + "." + this.getLiteral().replace( '-', '_' ), command + " " + this.getLiteral() ); } - private LiteralCommandNode buildImpl(String id, String command) { - HelpCommand helpCommand = new HelpCommand(id, command); - LiteralCommandNode node = new LiteralCommandNode<>(this.getLiteral(), - helpCommand, this.getRequirement(), - this.getRedirect(), this.getRedirectModifier(), this.isFork()); + private LiteralCommandNode buildImpl( String id, String command ) + { + HelpCommand helpCommand = new HelpCommand( id, command ); + LiteralCommandNode node = new LiteralCommandNode<>( this.getLiteral(), + helpCommand, this.getRequirement(), + this.getRedirect(), this.getRedirectModifier(), this.isFork() ); helpCommand.node = node; // Set up a /... help command LiteralArgumentBuilder helpNode = - LiteralArgumentBuilder.literal("help").requires(x -> this.getArguments().stream() - .anyMatch( - y -> y.getRequirement() - .test( - x))) - .executes(helpCommand); + LiteralArgumentBuilder.literal( "help" ).requires( x -> this.getArguments().stream() + .anyMatch( + y -> y.getRequirement() + .test( + x ) ) ) + .executes( helpCommand ); // Add all normal command children to this and the help node - for (CommandNode child : this.getArguments()) { - node.addChild(child); + for( CommandNode child : this.getArguments() ) + { + node.addChild( child ); - helpNode.then(LiteralArgumentBuilder.literal(child.getName()).requires(child.getRequirement()) - .executes(helpForChild(child, id, command)) - .build()); + helpNode.then( LiteralArgumentBuilder.literal( child.getName() ).requires( child.getRequirement() ) + .executes( helpForChild( child, id, command ) ) + .build() ); } // And add alternative versions of which forward instead - for (HelpingArgumentBuilder childBuilder : this.children) { - LiteralCommandNode child = childBuilder.build(id, command); - node.addChild(child); - helpNode.then(LiteralArgumentBuilder.literal(child.getName()).requires(child.getRequirement()) - .executes(helpForChild(child, id, command)) - .redirect(child.getChild("help")) - .build()); + for( HelpingArgumentBuilder childBuilder : this.children ) + { + LiteralCommandNode child = childBuilder.build( id, command ); + node.addChild( child ); + helpNode.then( LiteralArgumentBuilder.literal( child.getName() ).requires( child.getRequirement() ) + .executes( helpForChild( child, id, command ) ) + .redirect( child.getChild( "help" ) ) + .build() ); } - node.addChild(helpNode.build()); + node.addChild( helpNode.build() ); return node; } - private static final class HelpCommand implements Command { + private static final class HelpCommand implements Command + { private final String id; private final String command; LiteralCommandNode node; - private HelpCommand(String id, String command) { + private HelpCommand( String id, String command ) + { this.id = id; this.command = command; } @Override - public int run(CommandContext context) { + public int run( CommandContext context ) + { context.getSource() - .sendFeedback(getHelp(context, this.node, this.id, this.command), false); + .sendFeedback( getHelp( context, this.node, this.id, this.command ), false ); return 0; } } diff --git a/src/main/java/dan200/computercraft/shared/command/text/ChatHelpers.java b/src/main/java/dan200/computercraft/shared/command/text/ChatHelpers.java index 56d4a7201..03a8deae0 100644 --- a/src/main/java/dan200/computercraft/shared/command/text/ChatHelpers.java +++ b/src/main/java/dan200/computercraft/shared/command/text/ChatHelpers.java @@ -82,7 +82,7 @@ public final class ChatHelpers style = style.withClickEvent( click ); style = style.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) ); - component.setStyle(style); + component.setStyle( style ); return component; } diff --git a/src/main/java/dan200/computercraft/shared/command/text/ServerTableFormatter.java b/src/main/java/dan200/computercraft/shared/command/text/ServerTableFormatter.java index e96081f77..4a48e8391 100644 --- a/src/main/java/dan200/computercraft/shared/command/text/ServerTableFormatter.java +++ b/src/main/java/dan200/computercraft/shared/command/text/ServerTableFormatter.java @@ -6,44 +6,50 @@ package dan200.computercraft.shared.command.text; -import javax.annotation.Nullable; - -import org.apache.commons.lang3.StringUtils; - import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; +import org.apache.commons.lang3.StringUtils; -public class ServerTableFormatter implements TableFormatter { +import javax.annotation.Nullable; + +public class ServerTableFormatter implements TableFormatter +{ private final ServerCommandSource source; - public ServerTableFormatter(ServerCommandSource source) { + public ServerTableFormatter( ServerCommandSource source ) + { this.source = source; } @Override @Nullable - public Text getPadding(Text component, int width) { - int extraWidth = width - this.getWidth(component); - if (extraWidth <= 0) { + public Text getPadding( Text component, int width ) + { + int extraWidth = width - this.getWidth( component ); + if( extraWidth <= 0 ) + { return null; } - return new LiteralText(StringUtils.repeat(' ', extraWidth)); + return new LiteralText( StringUtils.repeat( ' ', extraWidth ) ); } @Override - public int getColumnPadding() { + public int getColumnPadding() + { return 1; } @Override - public int getWidth(Text component) { + public int getWidth( Text component ) + { return component.getString() - .length(); + .length(); } @Override - public void writeLine(int id, Text component) { - this.source.sendFeedback(component, false); + public void writeLine( int id, Text component ) + { + this.source.sendFeedback( component, false ); } } diff --git a/src/main/java/dan200/computercraft/shared/command/text/TableBuilder.java b/src/main/java/dan200/computercraft/shared/command/text/TableBuilder.java index 89c9d9588..800068e29 100644 --- a/src/main/java/dan200/computercraft/shared/command/text/TableBuilder.java +++ b/src/main/java/dan200/computercraft/shared/command/text/TableBuilder.java @@ -6,65 +6,74 @@ package dan200.computercraft.shared.command.text; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.command.CommandUtils; import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.network.client.ChatTableClientMessage; - import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; -public class TableBuilder { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +public class TableBuilder +{ private final int id; private final Text[] headers; private final ArrayList rows = new ArrayList<>(); private int columns = -1; private int additional; - public TableBuilder(int id, @Nonnull Text... headers) { - if (id < 0) { - throw new IllegalArgumentException("ID must be positive"); + public TableBuilder( int id, @Nonnull Text... headers ) + { + if( id < 0 ) + { + throw new IllegalArgumentException( "ID must be positive" ); } this.id = id; this.headers = headers; this.columns = headers.length; } - public TableBuilder(int id) { - if (id < 0) { - throw new IllegalArgumentException("ID must be positive"); + public TableBuilder( int id ) + { + if( id < 0 ) + { + throw new IllegalArgumentException( "ID must be positive" ); } this.id = id; this.headers = null; } - public TableBuilder(int id, @Nonnull String... headers) { - if (id < 0) { - throw new IllegalArgumentException("ID must be positive"); + public TableBuilder( int id, @Nonnull String... headers ) + { + if( id < 0 ) + { + throw new IllegalArgumentException( "ID must be positive" ); } this.id = id; this.headers = new Text[headers.length]; this.columns = headers.length; - for (int i = 0; i < headers.length; i++) { - this.headers[i] = ChatHelpers.header(headers[i]); + for( int i = 0; i < headers.length; i++ ) + { + this.headers[i] = ChatHelpers.header( headers[i] ); } } - public void row(@Nonnull Text... row) { - if (this.columns == -1) { + public void row( @Nonnull Text... row ) + { + if( this.columns == -1 ) + { this.columns = row.length; } - if (row.length != this.columns) { - throw new IllegalArgumentException("Row is the incorrect length"); + if( row.length != this.columns ) + { + throw new IllegalArgumentException( "Row is the incorrect length" ); } - this.rows.add(row); + this.rows.add( row ); } /** @@ -74,7 +83,8 @@ public class TableBuilder { * * @return This table's type. */ - public int getId() { + public int getId() + { return this.id; } @@ -85,35 +95,44 @@ public class TableBuilder { * * @return The number of columns. */ - public int getColumns() { + public int getColumns() + { return this.columns; } @Nullable - public Text[] getHeaders() { + public Text[] getHeaders() + { return this.headers; } @Nonnull - public List getRows() { + public List getRows() + { return this.rows; } - public int getAdditional() { + public int getAdditional() + { return this.additional; } - public void setAdditional(int additional) { + public void setAdditional( int additional ) + { this.additional = additional; } - public void display(ServerCommandSource source) { - if (CommandUtils.isPlayer(source)) { - this.trim(18); - NetworkHandler.sendToPlayer((ServerPlayerEntity) source.getEntity(), new ChatTableClientMessage(this)); - } else { - this.trim(100); - new ServerTableFormatter(source).display(this); + public void display( ServerCommandSource source ) + { + if( CommandUtils.isPlayer( source ) ) + { + this.trim( 18 ); + NetworkHandler.sendToPlayer( (ServerPlayerEntity) source.getEntity(), new ChatTableClientMessage( this ) ); + } + else + { + this.trim( 100 ); + new ServerTableFormatter( source ).display( this ); } } @@ -122,11 +141,13 @@ public class TableBuilder { * * @param height The desired height. */ - public void trim(int height) { - if (this.rows.size() > height) { + public void trim( int height ) + { + if( this.rows.size() > height ) + { this.additional += this.rows.size() - height - 1; - this.rows.subList(height - 1, this.rows.size()) - .clear(); + this.rows.subList( height - 1, this.rows.size() ) + .clear(); } } } diff --git a/src/main/java/dan200/computercraft/shared/command/text/TableFormatter.java b/src/main/java/dan200/computercraft/shared/command/text/TableFormatter.java index 90c02e1ea..ae11ae058 100644 --- a/src/main/java/dan200/computercraft/shared/command/text/TableFormatter.java +++ b/src/main/java/dan200/computercraft/shared/command/text/TableFormatter.java @@ -6,23 +6,25 @@ package dan200.computercraft.shared.command.text; -import static dan200.computercraft.shared.command.text.ChatHelpers.coloured; -import static dan200.computercraft.shared.command.text.ChatHelpers.translate; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.StringUtils; - import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import org.apache.commons.lang3.StringUtils; -public interface TableFormatter { - Text SEPARATOR = coloured("| ", Formatting.GRAY); - Text HEADER = coloured("=", Formatting.GRAY); +import javax.annotation.Nullable; - default int display(TableBuilder table) { - if (table.getColumns() <= 0) { +import static dan200.computercraft.shared.command.text.ChatHelpers.coloured; +import static dan200.computercraft.shared.command.text.ChatHelpers.translate; + +public interface TableFormatter +{ + Text SEPARATOR = coloured( "| ", Formatting.GRAY ); + Text HEADER = coloured( "=", Formatting.GRAY ); + + default int display( TableBuilder table ) + { + if( table.getColumns() <= 0 ) + { return 0; } @@ -31,16 +33,21 @@ public interface TableFormatter { int[] maxWidths = new int[columns]; Text[] headers = table.getHeaders(); - if (headers != null) { - for (int i = 0; i < columns; i++) { - maxWidths[i] = this.getWidth(headers[i]); + if( headers != null ) + { + for( int i = 0; i < columns; i++ ) + { + maxWidths[i] = this.getWidth( headers[i] ); } } - for (Text[] row : table.getRows()) { - for (int i = 0; i < row.length; i++) { - int width = this.getWidth(row[i]); - if (width > maxWidths[i]) { + for( Text[] row : table.getRows() ) + { + for( int i = 0; i < row.length; i++ ) + { + int width = this.getWidth( row[i] ); + if( width > maxWidths[i] ) + { maxWidths[i] = width; } } @@ -49,60 +56,69 @@ public interface TableFormatter { // Add a small amount of padding after each column { int padding = this.getColumnPadding(); - for (int i = 0; i < maxWidths.length - 1; i++) { + for( int i = 0; i < maxWidths.length - 1; i++ ) + { maxWidths[i] += padding; } } // And compute the total width - int totalWidth = (columns - 1) * this.getWidth(SEPARATOR); - for (int x : maxWidths) { + int totalWidth = (columns - 1) * this.getWidth( SEPARATOR ); + for( int x : maxWidths ) + { totalWidth += x; } - if (headers != null) { - LiteralText line = new LiteralText(""); - for (int i = 0; i < columns - 1; i++) { - line.append(headers[i]); - Text padding = this.getPadding(headers[i], maxWidths[i]); - if (padding != null) { - line.append(padding); + if( headers != null ) + { + LiteralText line = new LiteralText( "" ); + for( int i = 0; i < columns - 1; i++ ) + { + line.append( headers[i] ); + Text padding = this.getPadding( headers[i], maxWidths[i] ); + if( padding != null ) + { + line.append( padding ); } - line.append(SEPARATOR); + line.append( SEPARATOR ); } - line.append(headers[columns - 1]); + line.append( headers[columns - 1] ); - this.writeLine(rowId++, line); + this.writeLine( rowId++, line ); // Write a separator line. We round the width up rather than down to make // it a tad prettier. - int rowCharWidth = this.getWidth(HEADER); + int rowCharWidth = this.getWidth( HEADER ); int rowWidth = totalWidth / rowCharWidth + (totalWidth % rowCharWidth == 0 ? 0 : 1); - this.writeLine(rowId++, coloured(StringUtils.repeat(HEADER.getString(), rowWidth), Formatting.GRAY)); + this.writeLine( rowId++, coloured( StringUtils.repeat( HEADER.getString(), rowWidth ), Formatting.GRAY ) ); } - for (Text[] row : table.getRows()) { - LiteralText line = new LiteralText(""); - for (int i = 0; i < columns - 1; i++) { - line.append(row[i]); - Text padding = this.getPadding(row[i], maxWidths[i]); - if (padding != null) { - line.append(padding); + for( Text[] row : table.getRows() ) + { + LiteralText line = new LiteralText( "" ); + for( int i = 0; i < columns - 1; i++ ) + { + line.append( row[i] ); + Text padding = this.getPadding( row[i], maxWidths[i] ); + if( padding != null ) + { + line.append( padding ); } - line.append(SEPARATOR); + line.append( SEPARATOR ); } - line.append(row[columns - 1]); - this.writeLine(rowId++, line); + line.append( row[columns - 1] ); + this.writeLine( rowId++, line ); } - if (table.getAdditional() > 0) { - this.writeLine(rowId++, coloured(translate("commands.computercraft.generic.additional_rows", table.getAdditional()), Formatting.AQUA)); + if( table.getAdditional() > 0 ) + { + this.writeLine( rowId++, coloured( translate( "commands.computercraft.generic.additional_rows", table.getAdditional() ), Formatting.AQUA ) ); } return rowId - table.getId(); } - int getWidth(Text component); + int getWidth( Text component ); /** * Get the minimum padding between each column. @@ -115,11 +131,11 @@ public interface TableFormatter { * Get additional padding for the component. * * @param component The component to pad - * @param width The desired width for the component + * @param width The desired width for the component * @return The padding for this component, or {@code null} if none is needed. */ @Nullable - Text getPadding(Text component, int width); + Text getPadding( Text component, int width ); - void writeLine(int id, Text component); + void writeLine( int id, Text component ); } diff --git a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java index 95a16920f..5b5ce5a32 100644 --- a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.common; -import java.util.Random; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import net.minecraft.block.Block; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; @@ -26,40 +21,52 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.BlockView; import net.minecraft.world.World; -public abstract class BlockGeneric extends BlockWithEntity { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Random; + +public abstract class BlockGeneric extends BlockWithEntity +{ private final BlockEntityType type; - public BlockGeneric(Settings settings, BlockEntityType type) { - super(settings); + public BlockGeneric( Settings settings, BlockEntityType type ) + { + super( settings ); this.type = type; } @Override - public BlockRenderType getRenderType(BlockState state) { + public BlockRenderType getRenderType( BlockState state ) + { return BlockRenderType.MODEL; } @Override @Deprecated - public final void neighborUpdate(@Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, - @Nonnull BlockPos neighbourPos, boolean isMoving) { - BlockEntity tile = world.getBlockEntity(pos); - if (tile instanceof TileGeneric) { - ((TileGeneric) tile).onNeighbourChange(neighbourPos); + public final void neighborUpdate( @Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, + @Nonnull BlockPos neighbourPos, boolean isMoving ) + { + BlockEntity tile = world.getBlockEntity( pos ); + if( tile instanceof TileGeneric ) + { + ((TileGeneric) tile).onNeighbourChange( neighbourPos ); } } @Override @Deprecated - public final void onStateReplaced(@Nonnull BlockState block, @Nonnull World world, @Nonnull BlockPos pos, BlockState replace, boolean bool) { - if (block.getBlock() == replace.getBlock()) { + public final void onStateReplaced( @Nonnull BlockState block, @Nonnull World world, @Nonnull BlockPos pos, BlockState replace, boolean bool ) + { + if( block.getBlock() == replace.getBlock() ) + { return; } - BlockEntity tile = world.getBlockEntity(pos); - super.onStateReplaced(block, world, pos, replace, bool); - world.removeBlockEntity(pos); - if (tile instanceof TileGeneric) { + BlockEntity tile = world.getBlockEntity( pos ); + super.onStateReplaced( block, world, pos, replace, bool ); + world.removeBlockEntity( pos ); + if( tile instanceof TileGeneric ) + { ((TileGeneric) tile).destroy(); } } @@ -67,24 +74,28 @@ public abstract class BlockGeneric extends BlockWithEntity { @Nonnull @Override @Deprecated - public final ActionResult onUse(@Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull PlayerEntity player, @Nonnull Hand hand, - @Nonnull BlockHitResult hit) { - BlockEntity tile = world.getBlockEntity(pos); - return tile instanceof TileGeneric ? ((TileGeneric) tile).onActivate(player, hand, hit) : ActionResult.PASS; + public final ActionResult onUse( @Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull PlayerEntity player, @Nonnull Hand hand, + @Nonnull BlockHitResult hit ) + { + BlockEntity tile = world.getBlockEntity( pos ); + return tile instanceof TileGeneric ? ((TileGeneric) tile).onActivate( player, hand, hit ) : ActionResult.PASS; } @Override @Deprecated - public void scheduledTick(@Nonnull BlockState state, ServerWorld world, @Nonnull BlockPos pos, @Nonnull Random rand) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof TileGeneric) { + public void scheduledTick( @Nonnull BlockState state, ServerWorld world, @Nonnull BlockPos pos, @Nonnull Random rand ) + { + BlockEntity te = world.getBlockEntity( pos ); + if( te instanceof TileGeneric ) + { ((TileGeneric) te).blockTick(); } } @Nullable @Override - public BlockEntity createBlockEntity(@Nonnull BlockView world) { + public BlockEntity createBlockEntity( @Nonnull BlockView world ) + { return this.type.instantiate(); } } diff --git a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java index 5aa12c5b7..e3fd875fb 100644 --- a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java @@ -8,21 +8,23 @@ package dan200.computercraft.shared.common; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.network.client.TerminalState; - import net.minecraft.nbt.CompoundTag; -public class ClientTerminal implements ITerminal { +public class ClientTerminal implements ITerminal +{ private boolean m_colour; private Terminal m_terminal; private boolean m_terminalChanged; - public ClientTerminal(boolean colour) { + public ClientTerminal( boolean colour ) + { this.m_colour = colour; this.m_terminal = null; this.m_terminalChanged = false; } - public boolean pollTerminalChanged() { + public boolean pollTerminalChanged() + { boolean changed = this.m_terminalChanged; this.m_terminalChanged = false; return changed; @@ -31,48 +33,64 @@ public class ClientTerminal implements ITerminal { // ITerminal implementation @Override - public Terminal getTerminal() { + public Terminal getTerminal() + { return this.m_terminal; } @Override - public boolean isColour() { + public boolean isColour() + { return this.m_colour; } - public void read(TerminalState state) { + public void read( TerminalState state ) + { this.m_colour = state.colour; - if (state.hasTerminal()) { - this.resizeTerminal(state.width, state.height); - state.apply(this.m_terminal); - } else { + if( state.hasTerminal() ) + { + this.resizeTerminal( state.width, state.height ); + state.apply( this.m_terminal ); + } + else + { this.deleteTerminal(); } } - private void resizeTerminal(int width, int height) { - if (this.m_terminal == null) { - this.m_terminal = new Terminal(width, height, () -> this.m_terminalChanged = true); + private void resizeTerminal( int width, int height ) + { + if( this.m_terminal == null ) + { + this.m_terminal = new Terminal( width, height, () -> this.m_terminalChanged = true ); this.m_terminalChanged = true; - } else { - this.m_terminal.resize(width, height); + } + else + { + this.m_terminal.resize( width, height ); } } - private void deleteTerminal() { - if (this.m_terminal != null) { + private void deleteTerminal() + { + if( this.m_terminal != null ) + { this.m_terminal = null; this.m_terminalChanged = true; } } - public void readDescription(CompoundTag nbt) { - this.m_colour = nbt.getBoolean("colour"); - if (nbt.contains("terminal")) { - CompoundTag terminal = nbt.getCompound("terminal"); - this.resizeTerminal(terminal.getInt("term_width"), terminal.getInt("term_height")); - this.m_terminal.readFromNBT(terminal); - } else { + public void readDescription( CompoundTag nbt ) + { + this.m_colour = nbt.getBoolean( "colour" ); + if( nbt.contains( "terminal" ) ) + { + CompoundTag terminal = nbt.getCompound( "terminal" ); + this.resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) ); + this.m_terminal.readFromNBT( terminal ); + } + else + { this.deleteTerminal(); } } diff --git a/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java b/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java index 00b0990a9..251bb104b 100644 --- a/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java +++ b/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java @@ -6,11 +6,8 @@ package dan200.computercraft.shared.common; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.util.ColourTracker; import dan200.computercraft.shared.util.ColourUtils; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.RecipeSerializer; @@ -20,31 +17,44 @@ import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; import net.minecraft.world.World; -public final class ColourableRecipe extends SpecialCraftingRecipe { - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>(ColourableRecipe::new); +import javax.annotation.Nonnull; - private ColourableRecipe(Identifier id) { - super(id); +public final class ColourableRecipe extends SpecialCraftingRecipe +{ + public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( ColourableRecipe::new ); + + private ColourableRecipe( Identifier id ) + { + super( id ); } @Override - public boolean matches(@Nonnull CraftingInventory inv, @Nonnull World world) { + public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) + { boolean hasColourable = false; boolean hasDye = false; - for (int i = 0; i < inv.size(); i++) { - ItemStack stack = inv.getStack(i); - if (stack.isEmpty()) { + for( int i = 0; i < inv.size(); i++ ) + { + ItemStack stack = inv.getStack( i ); + if( stack.isEmpty() ) + { continue; } - if (stack.getItem() instanceof IColouredItem) { - if (hasColourable) { + if( stack.getItem() instanceof IColouredItem ) + { + if( hasColourable ) + { return false; } hasColourable = true; - } else if (ColourUtils.getStackColour(stack) != null) { + } + else if( ColourUtils.getStackColour( stack ) != null ) + { hasDye = true; - } else { + } + else + { return false; } } @@ -54,15 +64,18 @@ public final class ColourableRecipe extends SpecialCraftingRecipe { @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inv) { + public ItemStack craft( @Nonnull CraftingInventory inv ) + { ItemStack colourable = ItemStack.EMPTY; ColourTracker tracker = new ColourTracker(); - for (int i = 0; i < inv.size(); i++) { - ItemStack stack = inv.getStack(i); + for( int i = 0; i < inv.size(); i++ ) + { + ItemStack stack = inv.getStack( i ); - if (stack.isEmpty()) { + if( stack.isEmpty() ) + { continue; } else @@ -80,13 +93,15 @@ public final class ColourableRecipe extends SpecialCraftingRecipe { } @Override - public boolean fits(int x, int y) { + public boolean fits( int x, int y ) + { return x >= 2 && y >= 2; } @Override @Nonnull - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } } diff --git a/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java b/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java index 2bc83d038..3d22443a0 100644 --- a/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java +++ b/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java @@ -6,12 +6,9 @@ package dan200.computercraft.shared.common; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.network.container.HeldItemContainerData; - +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; @@ -23,49 +20,59 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Hand; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; -public class ContainerHeldItem extends ScreenHandler { +public class ContainerHeldItem extends ScreenHandler +{ private final ItemStack stack; private final Hand hand; - public ContainerHeldItem(ScreenHandlerType type, int id, PlayerEntity player, Hand hand) { - super(type, id); + public ContainerHeldItem( ScreenHandlerType type, int id, PlayerEntity player, Hand hand ) + { + super( type, id ); this.hand = hand; - this.stack = player.getStackInHand(hand) - .copy(); + this.stack = player.getStackInHand( hand ) + .copy(); } - public static ContainerHeldItem createPrintout(int id, PlayerInventory inventory, PacketByteBuf data) { - return createPrintout(id, inventory, new HeldItemContainerData(data)); + public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, PacketByteBuf data ) + { + return createPrintout( id, inventory, new HeldItemContainerData( data ) ); } - public static ContainerHeldItem createPrintout(int id, PlayerInventory inventory, HeldItemContainerData data) { - return new ContainerHeldItem(ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand()); + public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, HeldItemContainerData data ) + { + return new ContainerHeldItem( ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() ); } @Nonnull - public ItemStack getStack() { + public ItemStack getStack() + { return this.stack; } @Override - public boolean canUse(@Nonnull PlayerEntity player) { - if (!player.isAlive()) { + public boolean canUse( @Nonnull PlayerEntity player ) + { + if( !player.isAlive() ) + { return false; } - ItemStack stack = player.getStackInHand(this.hand); + ItemStack stack = player.getStackInHand( this.hand ); return stack == this.stack || !stack.isEmpty() && !this.stack.isEmpty() && stack.getItem() == this.stack.getItem(); } - public static class Factory implements NamedScreenHandlerFactory, ExtendedScreenHandlerFactory { + public static class Factory implements NamedScreenHandlerFactory, ExtendedScreenHandlerFactory + { private final ScreenHandlerType type; private final Text name; private final Hand hand; - public Factory(ScreenHandlerType type, ItemStack stack, Hand hand) { + public Factory( ScreenHandlerType type, ItemStack stack, Hand hand ) + { this.type = type; this.name = stack.getName(); this.hand = hand; @@ -73,19 +80,22 @@ public class ContainerHeldItem extends ScreenHandler { @Nonnull @Override - public Text getDisplayName() { + public Text getDisplayName() + { return this.name; } @Nullable @Override - public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) { - return new ContainerHeldItem(this.type, id, player, this.hand); + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) + { + return new ContainerHeldItem( this.type, id, player, this.hand ); } @Override - public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) { - packetByteBuf.writeEnumConstant(this.hand); + public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf ) + { + packetByteBuf.writeEnumConstant( this.hand ); } } } diff --git a/src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java b/src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java index da5fc974e..b1642f413 100644 --- a/src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java +++ b/src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java @@ -6,28 +6,32 @@ package dan200.computercraft.shared.common; -import javax.annotation.Nonnull; - import dan200.computercraft.api.redstone.IBundledRedstoneProvider; - import net.minecraft.block.Block; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class DefaultBundledRedstoneProvider implements IBundledRedstoneProvider { +import javax.annotation.Nonnull; + +public class DefaultBundledRedstoneProvider implements IBundledRedstoneProvider +{ @Override - public int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side) { - return getDefaultBundledRedstoneOutput(world, pos, side); + public int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) + { + return getDefaultBundledRedstoneOutput( world, pos, side ); } - public static int getDefaultBundledRedstoneOutput(World world, BlockPos pos, Direction side) { - Block block = world.getBlockState(pos) - .getBlock(); - if (block instanceof IBundledRedstoneBlock) { + public static int getDefaultBundledRedstoneOutput( World world, BlockPos pos, Direction side ) + { + Block block = world.getBlockState( pos ) + .getBlock(); + if( block instanceof IBundledRedstoneBlock ) + { IBundledRedstoneBlock generic = (IBundledRedstoneBlock) block; - if (generic.getBundledRedstoneConnectivity(world, pos, side)) { - return generic.getBundledRedstoneOutput(world, pos, side); + if( generic.getBundledRedstoneConnectivity( world, pos, side ) ) + { + return generic.getBundledRedstoneOutput( world, pos, side ); } } return -1; diff --git a/src/main/java/dan200/computercraft/shared/common/IBundledRedstoneBlock.java b/src/main/java/dan200/computercraft/shared/common/IBundledRedstoneBlock.java index a0a459727..0be19a1ff 100644 --- a/src/main/java/dan200/computercraft/shared/common/IBundledRedstoneBlock.java +++ b/src/main/java/dan200/computercraft/shared/common/IBundledRedstoneBlock.java @@ -10,8 +10,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public interface IBundledRedstoneBlock { - boolean getBundledRedstoneConnectivity(World world, BlockPos pos, Direction side); +public interface IBundledRedstoneBlock +{ + boolean getBundledRedstoneConnectivity( World world, BlockPos pos, Direction side ); - int getBundledRedstoneOutput(World world, BlockPos pos, Direction side); + int getBundledRedstoneOutput( World world, BlockPos pos, Direction side ); } diff --git a/src/main/java/dan200/computercraft/shared/common/IColouredItem.java b/src/main/java/dan200/computercraft/shared/common/IColouredItem.java index 05cf3a0f2..d654d9466 100644 --- a/src/main/java/dan200/computercraft/shared/common/IColouredItem.java +++ b/src/main/java/dan200/computercraft/shared/common/IColouredItem.java @@ -9,33 +9,42 @@ package dan200.computercraft.shared.common; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; -public interface IColouredItem { +public interface IColouredItem +{ String NBT_COLOUR = "Color"; - default int getColour(ItemStack stack) { - return getColourBasic(stack); + default int getColour( ItemStack stack ) + { + return getColourBasic( stack ); } - static int getColourBasic(ItemStack stack) { + static int getColourBasic( ItemStack stack ) + { CompoundTag tag = stack.getTag(); - return tag != null && tag.contains(NBT_COLOUR) ? tag.getInt(NBT_COLOUR) : -1; + return tag != null && tag.contains( NBT_COLOUR ) ? tag.getInt( NBT_COLOUR ) : -1; } - default ItemStack withColour(ItemStack stack, int colour) { + default ItemStack withColour( ItemStack stack, int colour ) + { ItemStack copy = stack.copy(); - setColourBasic(copy, colour); + setColourBasic( copy, colour ); return copy; } - static void setColourBasic(ItemStack stack, int colour) { - if (colour == -1) { + static void setColourBasic( ItemStack stack, int colour ) + { + if( colour == -1 ) + { CompoundTag tag = stack.getTag(); - if (tag != null) { - tag.remove(NBT_COLOUR); + if( tag != null ) + { + tag.remove( NBT_COLOUR ); } - } else { + } + else + { stack.getOrCreateTag() - .putInt(NBT_COLOUR, colour); + .putInt( NBT_COLOUR, colour ); } } } diff --git a/src/main/java/dan200/computercraft/shared/common/ITerminal.java b/src/main/java/dan200/computercraft/shared/common/ITerminal.java index 75dc8196c..2a6a9a9e0 100644 --- a/src/main/java/dan200/computercraft/shared/common/ITerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ITerminal.java @@ -8,7 +8,8 @@ package dan200.computercraft.shared.common; import dan200.computercraft.core.terminal.Terminal; -public interface ITerminal { +public interface ITerminal +{ Terminal getTerminal(); boolean isColour(); diff --git a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java index 25153a647..294335aa1 100644 --- a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java @@ -6,79 +6,95 @@ package dan200.computercraft.shared.common; -import java.util.concurrent.atomic.AtomicBoolean; - import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.network.client.TerminalState; - import net.minecraft.nbt.CompoundTag; -public class ServerTerminal implements ITerminal { +import java.util.concurrent.atomic.AtomicBoolean; + +public class ServerTerminal implements ITerminal +{ private final boolean m_colour; - private final AtomicBoolean m_terminalChanged = new AtomicBoolean(false); + private final AtomicBoolean m_terminalChanged = new AtomicBoolean( false ); private Terminal m_terminal; private boolean m_terminalChangedLastFrame = false; - public ServerTerminal(boolean colour) { + public ServerTerminal( boolean colour ) + { this.m_colour = colour; this.m_terminal = null; } - public ServerTerminal(boolean colour, int terminalWidth, int terminalHeight) { + public ServerTerminal( boolean colour, int terminalWidth, int terminalHeight ) + { this.m_colour = colour; - this.m_terminal = new Terminal(terminalWidth, terminalHeight, this::markTerminalChanged); + this.m_terminal = new Terminal( terminalWidth, terminalHeight, this::markTerminalChanged ); } - protected void markTerminalChanged() { - this.m_terminalChanged.set(true); + protected void markTerminalChanged() + { + this.m_terminalChanged.set( true ); } - protected void resize(int width, int height) { - if (this.m_terminal == null) { - this.m_terminal = new Terminal(width, height, this::markTerminalChanged); + protected void resize( int width, int height ) + { + if( this.m_terminal == null ) + { + this.m_terminal = new Terminal( width, height, this::markTerminalChanged ); this.markTerminalChanged(); - } else { - this.m_terminal.resize(width, height); + } + else + { + this.m_terminal.resize( width, height ); } } - public void delete() { - if (this.m_terminal != null) { + public void delete() + { + if( this.m_terminal != null ) + { this.m_terminal = null; this.markTerminalChanged(); } } - public void update() { - this.m_terminalChangedLastFrame = this.m_terminalChanged.getAndSet(false); + public void update() + { + this.m_terminalChangedLastFrame = this.m_terminalChanged.getAndSet( false ); } - public boolean hasTerminalChanged() { + public boolean hasTerminalChanged() + { return this.m_terminalChangedLastFrame; } @Override - public Terminal getTerminal() { + public Terminal getTerminal() + { return this.m_terminal; } @Override - public boolean isColour() { + public boolean isColour() + { return this.m_colour; } - public TerminalState write() { - return new TerminalState(this.m_colour, this.m_terminal); + public TerminalState write() + { + return new TerminalState( this.m_colour, this.m_terminal ); } - public void writeDescription(CompoundTag nbt) { - nbt.putBoolean("colour", this.m_colour); - if (this.m_terminal != null) { + public void writeDescription( CompoundTag nbt ) + { + nbt.putBoolean( "colour", this.m_colour ); + if( this.m_terminal != null ) + { CompoundTag terminal = new CompoundTag(); - terminal.putInt("term_width", this.m_terminal.getWidth()); - terminal.putInt("term_height", this.m_terminal.getHeight()); - this.m_terminal.writeToNBT(terminal); - nbt.put("terminal", terminal); + terminal.putInt( "term_width", this.m_terminal.getWidth() ); + terminal.putInt( "term_height", this.m_terminal.getHeight() ); + this.m_terminal.writeToNBT( terminal ); + nbt.put( "terminal", terminal ); } } } diff --git a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java index a2d37e532..a1936ca4d 100644 --- a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java @@ -6,8 +6,7 @@ package dan200.computercraft.shared.common; -import javax.annotation.Nonnull; - +import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -18,71 +17,88 @@ import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; -import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; +import javax.annotation.Nonnull; -public abstract class TileGeneric extends BlockEntity implements BlockEntityClientSerializable { - public TileGeneric(BlockEntityType type) { - super(type); +public abstract class TileGeneric extends BlockEntity implements BlockEntityClientSerializable +{ + public TileGeneric( BlockEntityType type ) + { + super( type ); } - public void destroy() { + public void destroy() + { } - public void onChunkUnloaded() { + public void onChunkUnloaded() + { } - public final void updateBlock() { + public final void updateBlock() + { this.markDirty(); BlockPos pos = this.getPos(); BlockState state = this.getCachedState(); - this.getWorld().updateListeners(pos, state, state, 3); + this.getWorld().updateListeners( pos, state, state, 3 ); } @Nonnull - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { return ActionResult.PASS; } - public void onNeighbourChange(@Nonnull BlockPos neighbour) { + public void onNeighbourChange( @Nonnull BlockPos neighbour ) + { } - public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) { + public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) + { } - protected void blockTick() { + protected void blockTick() + { } - public boolean isUsable(PlayerEntity player, boolean ignoreRange) { - if (player == null || !player.isAlive() || this.getWorld().getBlockEntity(this.getPos()) != this) { + public boolean isUsable( PlayerEntity player, boolean ignoreRange ) + { + if( player == null || !player.isAlive() || this.getWorld().getBlockEntity( this.getPos() ) != this ) + { return false; } - if (ignoreRange) { + if( ignoreRange ) + { return true; } - double range = this.getInteractRange(player); + double range = this.getInteractRange( player ); BlockPos pos = this.getPos(); - return player.getEntityWorld() == this.getWorld() && player.squaredDistanceTo(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) <= range * range; + return player.getEntityWorld() == this.getWorld() && player.squaredDistanceTo( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ) <= range * range; } - protected double getInteractRange(PlayerEntity player) { + protected double getInteractRange( PlayerEntity player ) + { return 8.0; } @Override - public void fromClientTag(CompoundTag compoundTag) { - this.readDescription(compoundTag); + public void fromClientTag( CompoundTag compoundTag ) + { + this.readDescription( compoundTag ); } - protected void readDescription(@Nonnull CompoundTag nbt) { + protected void readDescription( @Nonnull CompoundTag nbt ) + { } @Override - public CompoundTag toClientTag(CompoundTag compoundTag) { - this.writeDescription(compoundTag); + public CompoundTag toClientTag( CompoundTag compoundTag ) + { + this.writeDescription( compoundTag ); return compoundTag; } - protected void writeDescription(@Nonnull CompoundTag nbt) { + protected void writeDescription( @Nonnull CompoundTag nbt ) + { } } diff --git a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java index 4966ba1ca..dd52f0bb0 100644 --- a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java +++ b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java @@ -6,24 +6,13 @@ package dan200.computercraft.shared.computer.apis; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import com.google.common.collect.ImmutableMap; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.*; import dan200.computercraft.shared.computer.blocks.TileCommandComputer; import dan200.computercraft.shared.util.NBTUtil; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -36,19 +25,24 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.World; +import java.util.*; + /** * @cc.module commands */ -public class CommandAPI implements ILuaAPI { +public class CommandAPI implements ILuaAPI +{ private final TileCommandComputer computer; - public CommandAPI(TileCommandComputer computer) { + public CommandAPI( TileCommandComputer computer ) + { this.computer = computer; } @Override - public String[] getNames() { - return new String[] {"commands"}; + public String[] getNames() + { + return new String[] { "commands" }; } /** @@ -60,48 +54,56 @@ public class CommandAPI implements ILuaAPI { * @cc.treturn { string... } The output of this command, as a list of lines. * @cc.treturn number|nil The number of "affected" objects, or `nil` if the command failed. The definition of this varies from command to command. * @cc.usage Set the block above the command computer to stone. - *
    +     * 
          *     commands.exec("setblock ~ ~1 ~ minecraft:stone")
          *     
    */ - @LuaFunction (mainThread = true) - public final Object[] exec(String command) { - return this.doCommand(command); + @LuaFunction( mainThread = true ) + public final Object[] exec( String command ) + { + return this.doCommand( command ); } - private Object[] doCommand(String command) { + private Object[] doCommand( String command ) + { MinecraftServer server = this.computer.getWorld() - .getServer(); - if (server == null || !server.areCommandBlocksEnabled()) { + .getServer(); + if( server == null || !server.areCommandBlocksEnabled() ) + { return new Object[] { false, - createOutput("Command blocks disabled by server") + createOutput( "Command blocks disabled by server" ) }; } CommandManager commandManager = server.getCommandManager(); TileCommandComputer.CommandReceiver receiver = this.computer.getReceiver(); - try { + try + { receiver.clearOutput(); - int result = commandManager.execute(this.computer.getSource(), command); + int result = commandManager.execute( this.computer.getSource(), command ); return new Object[] { result > 0, receiver.copyOutput(), result }; - } catch (Throwable t) { - if (ComputerCraft.logComputerErrors) { - ComputerCraft.log.error("Error running command.", t); + } + catch( Throwable t ) + { + if( ComputerCraft.logComputerErrors ) + { + ComputerCraft.log.error( "Error running command.", t ); } return new Object[] { false, - createOutput("Java Exception Thrown: " + t) + createOutput( "Java Exception Thrown: " + t ) }; } } - private static Object createOutput(String output) { - return new Object[] {output}; + private static Object createOutput( String output ) + { + return new Object[] { output }; } /** @@ -118,14 +120,15 @@ public class CommandAPI implements ILuaAPI { * @return The "task id". When this command has been executed, it will queue a `task_complete` event with a matching id. * @throws LuaException (hidden) If the task cannot be created. * @cc.usage Asynchronously sets the block above the computer to stone. - *
    +     * 
          *     commands.execAsync("~ ~1 ~ minecraft:stone")
          *     
    * @cc.see parallel One may also use the parallel API to run multiple commands at once. */ @LuaFunction - public final long execAsync(ILuaContext context, String command) throws LuaException { - return context.issueMainThreadTask(() -> this.doCommand(command)); + public final long execAsync( ILuaContext context, String command ) throws LuaException + { + return context.issueMainThreadTask( () -> this.doCommand( command ) ); } /** @@ -136,29 +139,35 @@ public class CommandAPI implements ILuaAPI { * @throws LuaException (hidden) On non-string arguments. * @cc.tparam string ... The sub-command to complete. */ - @LuaFunction (mainThread = true) - public final List list(IArguments args) throws LuaException { + @LuaFunction( mainThread = true ) + public final List list( IArguments args ) throws LuaException + { MinecraftServer server = this.computer.getWorld() - .getServer(); + .getServer(); - if (server == null) { + if( server == null ) + { return Collections.emptyList(); } CommandNode node = server.getCommandManager() - .getDispatcher() - .getRoot(); - for (int j = 0; j < args.count(); j++) { - String name = args.getString(j); - node = node.getChild(name); - if (!(node instanceof LiteralCommandNode)) { + .getDispatcher() + .getRoot(); + for( int j = 0; j < args.count(); j++ ) + { + String name = args.getString( j ); + node = node.getChild( name ); + if( !(node instanceof LiteralCommandNode) ) + { return Collections.emptyList(); } } List result = new ArrayList<>(); - for (CommandNode child : node.getChildren()) { - if (child instanceof LiteralCommandNode) { - result.add(child.getName()); + for( CommandNode child : node.getChildren() ) + { + if( child instanceof LiteralCommandNode ) + { + result.add( child.getName() ); } } return result; @@ -174,7 +183,8 @@ public class CommandAPI implements ILuaAPI { * @cc.see gps.locate To get the position of a non-command computer. */ @LuaFunction - public final Object[] getBlockPosition() { + public final Object[] getBlockPosition() + { // This is probably safe to do on the Lua thread. Probably. BlockPos pos = this.computer.getPos(); return new Object[] { @@ -201,27 +211,33 @@ public class CommandAPI implements ILuaAPI { * @throws LuaException If the coordinates are not within the world. * @throws LuaException If trying to get information about more than 4096 blocks. */ - @LuaFunction (mainThread = true) - public final List> getBlockInfos(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) throws LuaException { + @LuaFunction( mainThread = true ) + public final List> getBlockInfos( int minX, int minY, int minZ, int maxX, int maxY, int maxZ ) throws LuaException + { // Get the details of the block World world = this.computer.getWorld(); - BlockPos min = new BlockPos(Math.min(minX, maxX), Math.min(minY, maxY), Math.min(minZ, maxZ)); - BlockPos max = new BlockPos(Math.max(minX, maxX), Math.max(minY, maxY), Math.max(minZ, maxZ)); - if (!World.isInBuildLimit(min) || !World.isInBuildLimit(max)) { - throw new LuaException("Co-ordinates out of range"); + BlockPos min = new BlockPos( Math.min( minX, maxX ), Math.min( minY, maxY ), Math.min( minZ, maxZ ) ); + BlockPos max = new BlockPos( Math.max( minX, maxX ), Math.max( minY, maxY ), Math.max( minZ, maxZ ) ); + if( !World.isInBuildLimit( min ) || !World.isInBuildLimit( max ) ) + { + throw new LuaException( "Co-ordinates out of range" ); } int blocks = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1); - if (blocks > 4096) { - throw new LuaException("Too many blocks"); + if( blocks > 4096 ) + { + throw new LuaException( "Too many blocks" ); } - List> results = new ArrayList<>(blocks); - for (int y = min.getY(); y <= max.getY(); y++) { - for (int z = min.getZ(); z <= max.getZ(); z++) { - for (int x = min.getX(); x <= max.getX(); x++) { - BlockPos pos = new BlockPos(x, y, z); - results.add(getBlockInfo(world, pos)); + List> results = new ArrayList<>( blocks ); + for( int y = min.getY(); y <= max.getY(); y++ ) + { + for( int z = min.getZ(); z <= max.getZ(); z++ ) + { + for( int x = min.getX(); x <= max.getX(); x++ ) + { + BlockPos pos = new BlockPos( x, y, z ); + results.add( getBlockInfo( world, pos ) ); } } } @@ -229,42 +245,47 @@ public class CommandAPI implements ILuaAPI { return results; } - private static Map getBlockInfo(World world, BlockPos pos) { + private static Map getBlockInfo( World world, BlockPos pos ) + { // Get the details of the block - BlockState state = world.getBlockState(pos); + BlockState state = world.getBlockState( pos ); Block block = state.getBlock(); Map table = new HashMap<>(); - table.put("name", - Registry.BLOCK.getId(block) - .toString()); - table.put("world", world.getRegistryKey()); + table.put( "name", + Registry.BLOCK.getId( block ) + .toString() ); + table.put( "world", world.getRegistryKey() ); Map stateTable = new HashMap<>(); - for (ImmutableMap.Entry, Comparable> entry : state.getEntries() - .entrySet()) { + for( ImmutableMap.Entry, Comparable> entry : state.getEntries() + .entrySet() ) + { Property property = entry.getKey(); - stateTable.put(property.getName(), getPropertyValue(property, entry.getValue())); + stateTable.put( property.getName(), getPropertyValue( property, entry.getValue() ) ); } - table.put("state", stateTable); + table.put( "state", stateTable ); - BlockEntity tile = world.getBlockEntity(pos); - if (tile != null) { - table.put("nbt", NBTUtil.toLua(tile.toTag(new CompoundTag()))); + BlockEntity tile = world.getBlockEntity( pos ); + if( tile != null ) + { + table.put( "nbt", NBTUtil.toLua( tile.toTag( new CompoundTag() ) ) ); } return table; } - @SuppressWarnings ({ + @SuppressWarnings( { "unchecked", "rawtypes" - }) - private static Object getPropertyValue(Property property, Comparable value) { - if (value instanceof String || value instanceof Number || value instanceof Boolean) { + } ) + private static Object getPropertyValue( Property property, Comparable value ) + { + if( value instanceof String || value instanceof Number || value instanceof Boolean ) + { return value; } - return property.name(value); + return property.name( value ); } /** @@ -279,15 +300,19 @@ public class CommandAPI implements ILuaAPI { * @return The given block's information. * @throws LuaException If the coordinates are not within the world, or are not currently loaded. */ - @LuaFunction (mainThread = true) - public final Map getBlockInfo(int x, int y, int z) throws LuaException { + @LuaFunction( mainThread = true ) + public final Map getBlockInfo( int x, int y, int z ) throws LuaException + { // Get the details of the block World world = this.computer.getWorld(); - BlockPos position = new BlockPos(x, y, z); - if (World.isInBuildLimit(position)) { - return getBlockInfo(world, position); - } else { - throw new LuaException("Co-ordinates out of range"); + BlockPos position = new BlockPos( x, y, z ); + if( World.isInBuildLimit( position ) ) + { + return getBlockInfo( world, position ); + } + else + { + throw new LuaException( "Co-ordinates out of range" ); } } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java index cb5971424..d64b679da 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java @@ -6,13 +6,9 @@ package dan200.computercraft.shared.computer.blocks; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.items.ComputerItemFactory; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; @@ -24,32 +20,40 @@ import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.Properties; import net.minecraft.util.math.Direction; -public class BlockComputer extends BlockComputerBase { - public static final EnumProperty STATE = EnumProperty.of("state", ComputerState.class); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class BlockComputer extends BlockComputerBase +{ + public static final EnumProperty STATE = EnumProperty.of( "state", ComputerState.class ); public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - public BlockComputer(Settings settings, ComputerFamily family, BlockEntityType type) { - super(settings, family, type); - this.setDefaultState(this.getDefaultState().with(FACING, Direction.NORTH) - .with(STATE, ComputerState.OFF)); + public BlockComputer( Settings settings, ComputerFamily family, BlockEntityType type ) + { + super( settings, family, type ); + this.setDefaultState( this.getDefaultState().with( FACING, Direction.NORTH ) + .with( STATE, ComputerState.OFF ) ); } @Nullable @Override - public BlockState getPlacementState(ItemPlacementContext placement) { - return this.getDefaultState().with(FACING, - placement.getPlayerFacing() - .getOpposite()); + public BlockState getPlacementState( ItemPlacementContext placement ) + { + return this.getDefaultState().with( FACING, + placement.getPlayerFacing() + .getOpposite() ); } @Override - protected void appendProperties(StateManager.Builder builder) { - builder.add(FACING, STATE); + protected void appendProperties( StateManager.Builder builder ) + { + builder.add( FACING, STATE ); } @Nonnull @Override - protected ItemStack getItem(TileComputerBase tile) { - return tile instanceof TileComputer ? ComputerItemFactory.create((TileComputer) tile) : ItemStack.EMPTY; + protected ItemStack getItem( TileComputerBase tile ) + { + return tile instanceof TileComputer ? ComputerItemFactory.create( (TileComputer) tile ) : ItemStack.EMPTY; } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java index 5ab2db712..a14f539d9 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java @@ -6,9 +6,6 @@ package dan200.computercraft.shared.computer.blocks; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.shared.common.BlockGeneric; @@ -16,7 +13,6 @@ import dan200.computercraft.shared.common.IBundledRedstoneBlock; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.items.IComputerItem; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -34,135 +30,162 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.BlockView; import net.minecraft.world.World; -public abstract class BlockComputerBase extends BlockGeneric implements IBundledRedstoneBlock { - private static final Identifier DROP = new Identifier(ComputerCraft.MOD_ID, "computer"); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BlockComputerBase extends BlockGeneric implements IBundledRedstoneBlock +{ + private static final Identifier DROP = new Identifier( ComputerCraft.MOD_ID, "computer" ); private final ComputerFamily family; - protected BlockComputerBase(Settings settings, ComputerFamily family, BlockEntityType type) { - super(settings, type); + protected BlockComputerBase( Settings settings, ComputerFamily family, BlockEntityType type ) + { + super( settings, type ); this.family = family; } @Override @Deprecated - public void onBlockAdded(@Nonnull BlockState state, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState oldState, boolean isMoving) { - super.onBlockAdded(state, world, pos, oldState, isMoving); + public void onBlockAdded( @Nonnull BlockState state, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState oldState, boolean isMoving ) + { + super.onBlockAdded( state, world, pos, oldState, isMoving ); - BlockEntity tile = world.getBlockEntity(pos); - if (tile instanceof TileComputerBase) { + BlockEntity tile = world.getBlockEntity( pos ); + if( tile instanceof TileComputerBase ) + { ((TileComputerBase) tile).updateInput(); } } @Override @Deprecated - public boolean emitsRedstonePower(@Nonnull BlockState state) { + public boolean emitsRedstonePower( @Nonnull BlockState state ) + { return true; } @Override @Deprecated - public int getWeakRedstonePower(@Nonnull BlockState state, @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide) { - return this.getStrongRedstonePower(state, world, pos, incomingSide); + public int getWeakRedstonePower( @Nonnull BlockState state, @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide ) + { + return this.getStrongRedstonePower( state, world, pos, incomingSide ); } @Override @Deprecated - public int getStrongRedstonePower(@Nonnull BlockState state, BlockView world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide) { - BlockEntity entity = world.getBlockEntity(pos); - if (!(entity instanceof TileComputerBase)) { + public int getStrongRedstonePower( @Nonnull BlockState state, BlockView world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide ) + { + BlockEntity entity = world.getBlockEntity( pos ); + if( !(entity instanceof TileComputerBase) ) + { return 0; } TileComputerBase computerEntity = (TileComputerBase) entity; ServerComputer computer = computerEntity.getServerComputer(); - if (computer == null) { + if( computer == null ) + { return 0; } - ComputerSide localSide = computerEntity.remapToLocalSide(incomingSide.getOpposite()); - return computer.getRedstoneOutput(localSide); + ComputerSide localSide = computerEntity.remapToLocalSide( incomingSide.getOpposite() ); + return computer.getRedstoneOutput( localSide ); } - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.family; } @Override - public boolean getBundledRedstoneConnectivity(World world, BlockPos pos, Direction side) { + public boolean getBundledRedstoneConnectivity( World world, BlockPos pos, Direction side ) + { return true; } @Override - public int getBundledRedstoneOutput(World world, BlockPos pos, Direction side) { - BlockEntity entity = world.getBlockEntity(pos); - if (!(entity instanceof TileComputerBase)) { + public int getBundledRedstoneOutput( World world, BlockPos pos, Direction side ) + { + BlockEntity entity = world.getBlockEntity( pos ); + if( !(entity instanceof TileComputerBase) ) + { return 0; } TileComputerBase computerEntity = (TileComputerBase) entity; ServerComputer computer = computerEntity.getServerComputer(); - if (computer == null) { + if( computer == null ) + { return 0; } - ComputerSide localSide = computerEntity.remapToLocalSide(side); - return computer.getBundledRedstoneOutput(localSide); + ComputerSide localSide = computerEntity.remapToLocalSide( side ); + return computer.getBundledRedstoneOutput( localSide ); } @Override - public void afterBreak(@Nonnull World world, PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity tile, - @Nonnull ItemStack tool) { + public void afterBreak( @Nonnull World world, PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity tile, + @Nonnull ItemStack tool ) + { // Don't drop blocks here - see onBlockHarvested. - player.incrementStat(Stats.MINED.getOrCreateStat(this)); - player.addExhaustion(0.005F); + player.incrementStat( Stats.MINED.getOrCreateStat( this ) ); + player.addExhaustion( 0.005F ); } @Override - public void onPlaced(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack) { - super.onPlaced(world, pos, state, placer, stack); + public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack ) + { + super.onPlaced( world, pos, state, placer, stack ); - BlockEntity tile = world.getBlockEntity(pos); - if (!world.isClient && tile instanceof IComputerTile && stack.getItem() instanceof IComputerItem) { + BlockEntity tile = world.getBlockEntity( pos ); + if( !world.isClient && tile instanceof IComputerTile && stack.getItem() instanceof IComputerItem ) + { IComputerTile computer = (IComputerTile) tile; IComputerItem item = (IComputerItem) stack.getItem(); - int id = item.getComputerID(stack); - if (id != -1) { - computer.setComputerID(id); + int id = item.getComputerID( stack ); + if( id != -1 ) + { + computer.setComputerID( id ); } - String label = item.getLabel(stack); - if (label != null) { - computer.setLabel(label); + String label = item.getLabel( stack ); + if( label != null ) + { + computer.setLabel( label ); } } } @Nonnull @Override - public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { - BlockEntity tile = world.getBlockEntity(pos); - if (tile instanceof TileComputerBase) { - ItemStack result = this.getItem((TileComputerBase) tile); - if (!result.isEmpty()) { + public ItemStack getPickStack( BlockView world, BlockPos pos, BlockState state ) + { + BlockEntity tile = world.getBlockEntity( pos ); + if( tile instanceof TileComputerBase ) + { + ItemStack result = this.getItem( (TileComputerBase) tile ); + if( !result.isEmpty() ) + { return result; } } - return super.getPickStack(world, pos, state); + return super.getPickStack( world, pos, state ); } @Nonnull - protected abstract ItemStack getItem(TileComputerBase tile); + protected abstract ItemStack getItem( TileComputerBase tile ); @Override - public void onBreak(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull PlayerEntity player) { + public void onBreak( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull PlayerEntity player ) + { // Call super as it is what provides sound and block break particles. Does not do anything else. - super.onBreak(world, pos, state, player); + super.onBreak( world, pos, state, player ); - if (!(world instanceof ServerWorld)) { + if( !(world instanceof ServerWorld) ) + { return; } ServerWorld serverWorld = (ServerWorld) world; @@ -170,20 +193,22 @@ public abstract class BlockComputerBase extends Bloc // We drop the item here instead of doing it in the harvest method, as we should // drop computers for creative players too. - BlockEntity tile = world.getBlockEntity(pos); - if (tile instanceof TileComputerBase) { + BlockEntity tile = world.getBlockEntity( pos ); + if( tile instanceof TileComputerBase ) + { TileComputerBase computer = (TileComputerBase) tile; - LootContext.Builder context = new LootContext.Builder(serverWorld).random(world.random) - .parameter(LootContextParameters.ORIGIN, Vec3d.ofCenter(pos)) - .parameter(LootContextParameters.TOOL, player.getMainHandStack()) - .parameter(LootContextParameters.THIS_ENTITY, player) - .parameter(LootContextParameters.BLOCK_ENTITY, tile) - .putDrop(DROP, (ctx, out) -> out.accept(this.getItem(computer))); - for (ItemStack item : state.getDroppedStacks(context)) { - dropStack(world, pos, item); + LootContext.Builder context = new LootContext.Builder( serverWorld ).random( world.random ) + .parameter( LootContextParameters.ORIGIN, Vec3d.ofCenter( pos ) ) + .parameter( LootContextParameters.TOOL, player.getMainHandStack() ) + .parameter( LootContextParameters.THIS_ENTITY, player ) + .parameter( LootContextParameters.BLOCK_ENTITY, tile ) + .putDrop( DROP, ( ctx, out ) -> out.accept( this.getItem( computer ) ) ); + for( ItemStack item : state.getDroppedStacks( context ) ) + { + dropStack( world, pos, item ); } - state.onStacksDropped(serverWorld, pos, player.getMainHandStack()); + state.onStacksDropped( serverWorld, pos, player.getMainHandStack() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java index c285650cb..86758b264 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java @@ -6,13 +6,13 @@ package dan200.computercraft.shared.computer.blocks; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.apis.OSAPI; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * A computer or turtle wrapped as a peripheral. * @@ -21,29 +21,34 @@ import dan200.computercraft.core.apis.OSAPI; * * @cc.module computer */ -public class ComputerPeripheral implements IPeripheral { +public class ComputerPeripheral implements IPeripheral +{ private final String type; private final ComputerProxy computer; - public ComputerPeripheral(String type, ComputerProxy computer) { + public ComputerPeripheral( String type, ComputerProxy computer ) + { this.type = type; this.computer = computer; } @Nonnull @Override - public String getType() { + public String getType() + { return this.type; } @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return this.computer.getTile(); } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return other instanceof ComputerPeripheral && this.computer == ((ComputerPeripheral) other).computer; } @@ -51,7 +56,8 @@ public class ComputerPeripheral implements IPeripheral { * Turn the other computer on. */ @LuaFunction - public final void turnOn() { + public final void turnOn() + { this.computer.turnOn(); } @@ -59,7 +65,8 @@ public class ComputerPeripheral implements IPeripheral { * Shutdown the other computer. */ @LuaFunction - public final void shutdown() { + public final void shutdown() + { this.computer.shutdown(); } @@ -67,7 +74,8 @@ public class ComputerPeripheral implements IPeripheral { * Reboot or turn on the other computer. */ @LuaFunction - public final void reboot() { + public final void reboot() + { this.computer.reboot(); } @@ -78,7 +86,8 @@ public class ComputerPeripheral implements IPeripheral { * @see OSAPI#getComputerID() To get your computer's ID. */ @LuaFunction - public final int getID() { + public final int getID() + { return this.computer.assignID(); } @@ -88,7 +97,8 @@ public class ComputerPeripheral implements IPeripheral { * @return If the computer is on. */ @LuaFunction - public final boolean isOn() { + public final boolean isOn() + { return this.computer.isOn(); } @@ -100,7 +110,8 @@ public class ComputerPeripheral implements IPeripheral { */ @Nullable @LuaFunction - public final String getLabel() { + public final String getLabel() + { return this.computer.getLabel(); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java index c2c52587d..b59a3c24a 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java @@ -6,67 +6,85 @@ package dan200.computercraft.shared.computer.blocks; -import java.util.function.Supplier; - import dan200.computercraft.shared.computer.core.IComputer; import dan200.computercraft.shared.computer.core.ServerComputer; +import java.util.function.Supplier; + /** * A proxy object for computer objects, delegating to {@link IComputer} or {@link TileComputer} where appropriate. */ -public class ComputerProxy { +public class ComputerProxy +{ private final Supplier get; - public ComputerProxy(Supplier get) { + public ComputerProxy( Supplier get ) + { this.get = get; } - public void turnOn() { + public void turnOn() + { TileComputerBase tile = this.getTile(); ServerComputer computer = tile.getServerComputer(); - if (computer == null) { + if( computer == null ) + { tile.m_startOn = true; - } else { + } + else + { computer.turnOn(); } } - protected TileComputerBase getTile() { + protected TileComputerBase getTile() + { return this.get.get(); } - public void shutdown() { + public void shutdown() + { TileComputerBase tile = this.getTile(); ServerComputer computer = tile.getServerComputer(); - if (computer == null) { + if( computer == null ) + { tile.m_startOn = false; - } else { + } + else + { computer.shutdown(); } } - public void reboot() { + public void reboot() + { TileComputerBase tile = this.getTile(); ServerComputer computer = tile.getServerComputer(); - if (computer == null) { + if( computer == null ) + { tile.m_startOn = true; - } else { + } + else + { computer.reboot(); } } - public int assignID() { + public int assignID() + { TileComputerBase tile = this.getTile(); ServerComputer computer = tile.getServerComputer(); return computer == null ? tile.getComputerID() : computer.getID(); } - public boolean isOn() { + public boolean isOn() + { ServerComputer computer = this.getTile().getServerComputer(); return computer != null && computer.isOn(); } - public String getLabel() { + public String getLabel() + { TileComputerBase tile = this.getTile(); ServerComputer computer = tile.getServerComputer(); return computer == null ? tile.getLabel() : computer.getLabel(); diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java b/src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java index 4e02f64c9..ba3e4fc0d 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java @@ -8,14 +8,15 @@ package dan200.computercraft.shared.computer.blocks; import dan200.computercraft.shared.computer.core.ComputerFamily; -public interface IComputerTile { +public interface IComputerTile +{ int getComputerID(); - void setComputerID(int id); + void setComputerID( int id ); String getLabel(); - void setLabel(String label); + void setLabel( String label ); ComputerFamily getFamily(); } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java index e29f14665..97d3c9e62 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java @@ -6,17 +6,10 @@ package dan200.computercraft.shared.computer.blocks; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.apis.CommandAPI; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.MinecraftServer; @@ -30,100 +23,125 @@ import net.minecraft.util.math.Vec2f; import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameRules; -public class TileCommandComputer extends TileComputer { +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class TileCommandComputer extends TileComputer +{ private final CommandReceiver receiver; - public TileCommandComputer(ComputerFamily family, BlockEntityType type) { - super(family, type); + public TileCommandComputer( ComputerFamily family, BlockEntityType type ) + { + super( family, type ); this.receiver = new CommandReceiver(); } - public CommandReceiver getReceiver() { + public CommandReceiver getReceiver() + { return this.receiver; } - public ServerCommandSource getSource() { + public ServerCommandSource getSource() + { ServerComputer computer = this.getServerComputer(); String name = "@"; - if (computer != null) { + if( computer != null ) + { String label = computer.getLabel(); - if (label != null) { + if( label != null ) + { name = label; } } - return new ServerCommandSource(this.receiver, - new Vec3d(this.pos.getX() + 0.5, this.pos.getY() + 0.5, this.pos.getZ() + 0.5), - Vec2f.ZERO, - (ServerWorld) this.getWorld(), - 2, - name, - new LiteralText(name), - this.getWorld().getServer(), - null); + return new ServerCommandSource( this.receiver, + new Vec3d( this.pos.getX() + 0.5, this.pos.getY() + 0.5, this.pos.getZ() + 0.5 ), + Vec2f.ZERO, + (ServerWorld) this.getWorld(), + 2, + name, + new LiteralText( name ), + this.getWorld().getServer(), + null ); } @Override - protected ServerComputer createComputer(int instanceID, int id) { - ServerComputer computer = super.createComputer(instanceID, id); - computer.addAPI(new CommandAPI(this)); + protected ServerComputer createComputer( int instanceID, int id ) + { + ServerComputer computer = super.createComputer( instanceID, id ); + computer.addAPI( new CommandAPI( this ) ); return computer; } @Override - public boolean isUsable(PlayerEntity player, boolean ignoreRange) { - return isUsable(player) && super.isUsable(player, ignoreRange); + public boolean isUsable( PlayerEntity player, boolean ignoreRange ) + { + return isUsable( player ) && super.isUsable( player, ignoreRange ); } - public static boolean isUsable(PlayerEntity player) { + public static boolean isUsable( PlayerEntity player ) + { MinecraftServer server = player.getServer(); - if (server == null || !server.areCommandBlocksEnabled()) { - player.sendMessage(new TranslatableText("advMode.notEnabled"), true); + if( server == null || !server.areCommandBlocksEnabled() ) + { + player.sendMessage( new TranslatableText( "advMode.notEnabled" ), true ); return false; - } else if (ComputerCraft.commandRequireCreative ? !player.isCreativeLevelTwoOp() : !server.getPlayerManager() - .isOperator(player.getGameProfile())) { - player.sendMessage(new TranslatableText("advMode.notAllowed"), true); + } + else if( ComputerCraft.commandRequireCreative ? !player.isCreativeLevelTwoOp() : !server.getPlayerManager() + .isOperator( player.getGameProfile() ) ) + { + player.sendMessage( new TranslatableText( "advMode.notAllowed" ), true ); return false; } return true; } - public class CommandReceiver implements CommandOutput { + public class CommandReceiver implements CommandOutput + { private final Map output = new HashMap<>(); - public void clearOutput() { + public void clearOutput() + { this.output.clear(); } - public Map getOutput() { + public Map getOutput() + { return this.output; } - public Map copyOutput() { - return new HashMap<>(this.output); + public Map copyOutput() + { + return new HashMap<>( this.output ); } @Override - public void sendSystemMessage(@Nonnull Text textComponent, @Nonnull UUID id) { - this.output.put(this.output.size() + 1, textComponent.getString()); + public void sendSystemMessage( @Nonnull Text textComponent, @Nonnull UUID id ) + { + this.output.put( this.output.size() + 1, textComponent.getString() ); } @Override - public boolean shouldReceiveFeedback() { + public boolean shouldReceiveFeedback() + { return TileCommandComputer.this.getWorld().getGameRules() - .getBoolean(GameRules.SEND_COMMAND_FEEDBACK); + .getBoolean( GameRules.SEND_COMMAND_FEEDBACK ); } @Override - public boolean shouldTrackOutput() { + public boolean shouldTrackOutput() + { return true; } @Override - public boolean shouldBroadcastConsoleToOps() { + public boolean shouldBroadcastConsoleToOps() + { return TileCommandComputer.this.getWorld().getGameRules() - .getBoolean(GameRules.COMMAND_BLOCK_OUTPUT); + .getBoolean( GameRules.COMMAND_BLOCK_OUTPUT ); } } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java index 3cd2b1908..5a487a1f4 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java @@ -6,16 +6,12 @@ package dan200.computercraft.shared.computer.blocks; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputer; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; @@ -23,62 +19,79 @@ import net.minecraft.entity.player.PlayerInventory; import net.minecraft.screen.ScreenHandler; import net.minecraft.util.math.Direction; -public class TileComputer extends TileComputerBase { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class TileComputer extends TileComputerBase +{ private ComputerProxy proxy; - public TileComputer(ComputerFamily family, BlockEntityType type) { - super(type, family); + public TileComputer( ComputerFamily family, BlockEntityType type ) + { + super( type, family ); } - public boolean isUsableByPlayer(PlayerEntity player) { - return this.isUsable(player, false); + public boolean isUsableByPlayer( PlayerEntity player ) + { + return this.isUsable( player, false ); } @Override - protected void updateBlockState(ComputerState newState) { + protected void updateBlockState( ComputerState newState ) + { BlockState existing = this.getCachedState(); - if (existing.get(BlockComputer.STATE) != newState) { - this.getWorld().setBlockState(this.getPos(), existing.with(BlockComputer.STATE, newState), 3); + if( existing.get( BlockComputer.STATE ) != newState ) + { + this.getWorld().setBlockState( this.getPos(), existing.with( BlockComputer.STATE, newState ), 3 ); } } @Override - public Direction getDirection() { - return this.getCachedState().get(BlockComputer.FACING); + public Direction getDirection() + { + return this.getCachedState().get( BlockComputer.FACING ); } @Override - protected ComputerSide remapLocalSide(ComputerSide localSide) { + protected ComputerSide remapLocalSide( ComputerSide localSide ) + { // For legacy reasons, computers invert the meaning of "left" and "right". A computer's front is facing // towards you, but a turtle's front is facing the other way. - if (localSide == ComputerSide.RIGHT) { + if( localSide == ComputerSide.RIGHT ) + { return ComputerSide.LEFT; } - if (localSide == ComputerSide.LEFT) { + if( localSide == ComputerSide.LEFT ) + { return ComputerSide.RIGHT; } return localSide; } @Override - protected ServerComputer createComputer(int instanceID, int id) { + protected ServerComputer createComputer( int instanceID, int id ) + { ComputerFamily family = this.getFamily(); - ServerComputer computer = new ServerComputer(this.getWorld(), - id, this.label, - instanceID, - family, - ComputerCraft.computerTermWidth, - ComputerCraft.computerTermHeight); - computer.setPosition(this.getPos()); + ServerComputer computer = new ServerComputer( this.getWorld(), + id, this.label, + instanceID, + family, + ComputerCraft.computerTermWidth, + ComputerCraft.computerTermHeight ); + computer.setPosition( this.getPos() ); return computer; } @Override - public ComputerProxy createProxy() { - if (this.proxy == null) { - this.proxy = new ComputerProxy(() -> this) { + public ComputerProxy createProxy() + { + if( this.proxy == null ) + { + this.proxy = new ComputerProxy( () -> this ) + { @Override - protected TileComputerBase getTile() { + protected TileComputerBase getTile() + { return TileComputer.this; } }; @@ -88,8 +101,9 @@ public class TileComputer extends TileComputerBase { @Nullable @Override - public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) { - return new ContainerComputer(id, this); + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) + { + return new ContainerComputer( id, this ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java index c12d44bc4..a0d1e6ea7 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.computer.blocks; -import java.util.Objects; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheralTile; @@ -25,7 +20,7 @@ import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.RedstoneUtil; import joptsimple.internal.Strings; - +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.RedstoneWireBlock; @@ -49,10 +44,13 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; public abstract class TileComputerBase extends TileGeneric implements IComputerTile, Tickable, IPeripheralTile, Nameable, NamedScreenHandlerFactory, - ExtendedScreenHandlerFactory { + ExtendedScreenHandlerFactory +{ private static final String NBT_ID = "ComputerId"; private static final String NBT_LABEL = "Label"; private static final String NBT_ON = "On"; @@ -64,16 +62,19 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT private boolean m_on = false; private boolean m_fresh = false; - public TileComputerBase(BlockEntityType type, ComputerFamily family) { - super(type); + public TileComputerBase( BlockEntityType type, ComputerFamily family ) + { + super( type ); this.family = family; } @Override - public void destroy() { + public void destroy() + { this.unload(); - for (Direction dir : DirectionUtil.FACINGS) { - RedstoneUtil.propagateRedstoneOutput(this.getWorld(), this.getPos(), dir); + for( Direction dir : DirectionUtil.FACINGS ) + { + RedstoneUtil.propagateRedstoneOutput( this.getWorld(), this.getPos(), dir ); } } @@ -83,10 +84,13 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT unload(); } - protected void unload() { - if (this.m_instanceID >= 0) { - if (!this.getWorld().isClient) { - ComputerCraft.serverComputerRegistry.remove(this.m_instanceID); + protected void unload() + { + if( this.m_instanceID >= 0 ) + { + if( !this.getWorld().isClient ) + { + ComputerCraft.serverComputerRegistry.remove( this.m_instanceID ); } this.m_instanceID = -1; } @@ -94,160 +98,194 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - ItemStack currentItem = player.getStackInHand(hand); - if (!currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && this.canNameWithTag(player) && currentItem.hasCustomName()) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + ItemStack currentItem = player.getStackInHand( hand ); + if( !currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && this.canNameWithTag( player ) && currentItem.hasCustomName() ) + { // Label to rename computer - if (!this.getWorld().isClient) { - this.setLabel(currentItem.getName() - .getString()); - currentItem.decrement(1); + if( !this.getWorld().isClient ) + { + this.setLabel( currentItem.getName() + .getString() ); + currentItem.decrement( 1 ); } return ActionResult.SUCCESS; - } else if (!player.isInSneakingPose()) { + } + else if( !player.isInSneakingPose() ) + { // Regular right click to activate computer - if (!this.getWorld().isClient && this.isUsable(player, false)) { + if( !this.getWorld().isClient && this.isUsable( player, false ) ) + { this.createServerComputer().turnOn(); - this.createServerComputer().sendTerminalState(player); - new ComputerContainerData(this.createServerComputer()).open(player, this); + this.createServerComputer().sendTerminalState( player ); + new ComputerContainerData( this.createServerComputer() ).open( player, this ); } return ActionResult.SUCCESS; } return ActionResult.PASS; } - protected boolean canNameWithTag(PlayerEntity player) { + protected boolean canNameWithTag( PlayerEntity player ) + { return false; } - public ServerComputer createServerComputer() { - if (this.getWorld().isClient) { + public ServerComputer createServerComputer() + { + if( this.getWorld().isClient ) + { return null; } boolean changed = false; - if (this.m_instanceID < 0) { + if( this.m_instanceID < 0 ) + { this.m_instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); changed = true; } - if (!ComputerCraft.serverComputerRegistry.contains(this.m_instanceID)) { - ServerComputer computer = this.createComputer(this.m_instanceID, this.m_computerID); - ComputerCraft.serverComputerRegistry.add(this.m_instanceID, computer); + if( !ComputerCraft.serverComputerRegistry.contains( this.m_instanceID ) ) + { + ServerComputer computer = this.createComputer( this.m_instanceID, this.m_computerID ); + ComputerCraft.serverComputerRegistry.add( this.m_instanceID, computer ); this.m_fresh = true; changed = true; } - if (changed) { + if( changed ) + { this.updateBlock(); this.updateInput(); } - return ComputerCraft.serverComputerRegistry.get(this.m_instanceID); + return ComputerCraft.serverComputerRegistry.get( this.m_instanceID ); } - public ServerComputer getServerComputer() { - return this.getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get(this.m_instanceID); + public ServerComputer getServerComputer() + { + return this.getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get( this.m_instanceID ); } - protected abstract ServerComputer createComputer(int instanceID, int id); + protected abstract ServerComputer createComputer( int instanceID, int id ); - public void updateInput() { - if (this.getWorld() == null || this.getWorld().isClient) { + public void updateInput() + { + if( this.getWorld() == null || this.getWorld().isClient ) + { return; } // Update all sides ServerComputer computer = this.getServerComputer(); - if (computer == null) { + if( computer == null ) + { return; } BlockPos pos = computer.getPosition(); - for (Direction dir : DirectionUtil.FACINGS) { - this.updateSideInput(computer, dir, pos.offset(dir)); + for( Direction dir : DirectionUtil.FACINGS ) + { + this.updateSideInput( computer, dir, pos.offset( dir ) ); } } - private void updateSideInput(ServerComputer computer, Direction dir, BlockPos offset) { + private void updateSideInput( ServerComputer computer, Direction dir, BlockPos offset ) + { Direction offsetSide = dir.getOpposite(); - ComputerSide localDir = this.remapToLocalSide(dir); + ComputerSide localDir = this.remapToLocalSide( dir ); - computer.setRedstoneInput(localDir, getRedstoneInput(this.world, offset, dir)); - computer.setBundledRedstoneInput(localDir, BundledRedstone.getOutput(this.getWorld(), offset, offsetSide)); - if (!this.isPeripheralBlockedOnSide(localDir)) { - IPeripheral peripheral = Peripherals.getPeripheral(this.getWorld(), offset, offsetSide); - computer.setPeripheral(localDir, peripheral); + computer.setRedstoneInput( localDir, getRedstoneInput( this.world, offset, dir ) ); + computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( this.getWorld(), offset, offsetSide ) ); + if( !this.isPeripheralBlockedOnSide( localDir ) ) + { + IPeripheral peripheral = Peripherals.getPeripheral( this.getWorld(), offset, offsetSide ); + computer.setPeripheral( localDir, peripheral ); } } - protected ComputerSide remapToLocalSide(Direction globalSide) { - return this.remapLocalSide(DirectionUtil.toLocal(this.getDirection(), globalSide)); + protected ComputerSide remapToLocalSide( Direction globalSide ) + { + return this.remapLocalSide( DirectionUtil.toLocal( this.getDirection(), globalSide ) ); } /** * Gets the redstone input for an adjacent block. * * @param world The world we exist in - * @param pos The position of the neighbour - * @param side The side we are reading from + * @param pos The position of the neighbour + * @param side The side we are reading from * @return The effective redstone power */ - protected static int getRedstoneInput(World world, BlockPos pos, Direction side) { - int power = world.getEmittedRedstonePower(pos, side); - if (power >= 15) { + protected static int getRedstoneInput( World world, BlockPos pos, Direction side ) + { + int power = world.getEmittedRedstonePower( pos, side ); + if( power >= 15 ) + { return power; } - BlockState neighbour = world.getBlockState(pos); - return neighbour.getBlock() == Blocks.REDSTONE_WIRE ? Math.max(power, neighbour.get(RedstoneWireBlock.POWER)) : power; + BlockState neighbour = world.getBlockState( pos ); + return neighbour.getBlock() == Blocks.REDSTONE_WIRE ? Math.max( power, neighbour.get( RedstoneWireBlock.POWER ) ) : power; } - protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) { + protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) + { return false; } - protected ComputerSide remapLocalSide(ComputerSide localSide) { + protected ComputerSide remapLocalSide( ComputerSide localSide ) + { return localSide; } protected abstract Direction getDirection(); @Override - public void onNeighbourChange(@Nonnull BlockPos neighbour) { - this.updateInput(neighbour); + public void onNeighbourChange( @Nonnull BlockPos neighbour ) + { + this.updateInput( neighbour ); } @Override - public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) { - this.updateInput(neighbour); + public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) + { + this.updateInput( neighbour ); } @Override - protected void readDescription(@Nonnull CompoundTag nbt) { - super.readDescription(nbt); - this.label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null; - this.m_computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1; + protected void readDescription( @Nonnull CompoundTag nbt ) + { + super.readDescription( nbt ); + this.label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; + this.m_computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; } @Override - protected void writeDescription(@Nonnull CompoundTag nbt) { - super.writeDescription(nbt); - if (this.label != null) { - nbt.putString(NBT_LABEL, this.label); + protected void writeDescription( @Nonnull CompoundTag nbt ) + { + super.writeDescription( nbt ); + if( this.label != null ) + { + nbt.putString( NBT_LABEL, this.label ); } - if (this.m_computerID >= 0) { - nbt.putInt(NBT_ID, this.m_computerID); + if( this.m_computerID >= 0 ) + { + nbt.putInt( NBT_ID, this.m_computerID ); } } @Override - public void tick() { - if (!this.getWorld().isClient) { + public void tick() + { + if( !this.getWorld().isClient ) + { ServerComputer computer = this.createServerComputer(); - if (computer == null) { + if( computer == null ) + { return; } // If the computer isn't on and should be, then turn it on - if (this.m_startOn || (this.m_fresh && this.m_on)) { + if( this.m_startOn || (this.m_fresh && this.m_on) ) + { computer.turnOn(); this.m_startOn = false; } @@ -259,75 +297,89 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT this.label = computer.getLabel(); this.m_on = computer.isOn(); - if (computer.hasOutputChanged()) { + if( computer.hasOutputChanged() ) + { this.updateOutput(); } // Update the block state if needed. We don't fire a block update intentionally, // as this only really is needed on the client side. - this.updateBlockState(computer.getState()); + this.updateBlockState( computer.getState() ); - if (computer.hasOutputChanged()) { + if( computer.hasOutputChanged() ) + { this.updateOutput(); } } } - public void updateOutput() { + public void updateOutput() + { // Update redstone this.updateBlock(); - for (Direction dir : DirectionUtil.FACINGS) { - RedstoneUtil.propagateRedstoneOutput(this.getWorld(), this.getPos(), dir); + for( Direction dir : DirectionUtil.FACINGS ) + { + RedstoneUtil.propagateRedstoneOutput( this.getWorld(), this.getPos(), dir ); } } - protected abstract void updateBlockState(ComputerState newState); + protected abstract void updateBlockState( ComputerState newState ); @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); // Load ID, label and power state - this.m_computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1; - this.label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null; - this.m_on = this.m_startOn = nbt.getBoolean(NBT_ON); + this.m_computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; + this.label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; + this.m_on = this.m_startOn = nbt.getBoolean( NBT_ON ); } @Nonnull @Override - public CompoundTag toTag(@Nonnull CompoundTag nbt) { + public CompoundTag toTag( @Nonnull CompoundTag nbt ) + { // Save ID, label and power state - if (this.m_computerID >= 0) { - nbt.putInt(NBT_ID, this.m_computerID); + if( this.m_computerID >= 0 ) + { + nbt.putInt( NBT_ID, this.m_computerID ); } - if (this.label != null) { - nbt.putString(NBT_LABEL, this.label); + if( this.label != null ) + { + nbt.putString( NBT_LABEL, this.label ); } - nbt.putBoolean(NBT_ON, this.m_on); + nbt.putBoolean( NBT_ON, this.m_on ); - return super.toTag(nbt); + return super.toTag( nbt ); } @Override - public void markRemoved() { + public void markRemoved() + { this.unload(); super.markRemoved(); } - private void updateInput(BlockPos neighbour) { - if (this.getWorld() == null || this.getWorld().isClient) { + private void updateInput( BlockPos neighbour ) + { + if( this.getWorld() == null || this.getWorld().isClient ) + { return; } ServerComputer computer = this.getServerComputer(); - if (computer == null) { + if( computer == null ) + { return; } - for (Direction dir : DirectionUtil.FACINGS) { - BlockPos offset = this.pos.offset(dir); - if (offset.equals(neighbour)) { - this.updateSideInput(computer, dir, offset); + for( Direction dir : DirectionUtil.FACINGS ) + { + BlockPos offset = this.pos.offset( dir ); + if( offset.equals( neighbour ) ) + { + this.updateSideInput( computer, dir, offset ); return; } } @@ -336,66 +388,80 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT this.updateInput(); } - private void updateInput(Direction dir) { - if (this.getWorld() == null || this.getWorld().isClient) { + private void updateInput( Direction dir ) + { + if( this.getWorld() == null || this.getWorld().isClient ) + { return; } ServerComputer computer = this.getServerComputer(); - if (computer == null) { + if( computer == null ) + { return; } - this.updateSideInput(computer, dir, this.pos.offset(dir)); + this.updateSideInput( computer, dir, this.pos.offset( dir ) ); } @Override - public final int getComputerID() { + public final int getComputerID() + { return this.m_computerID; } @Override - public final void setComputerID(int id) { - if (this.getWorld().isClient || this.m_computerID == id) { + public final void setComputerID( int id ) + { + if( this.getWorld().isClient || this.m_computerID == id ) + { return; } this.m_computerID = id; ServerComputer computer = this.getServerComputer(); - if (computer != null) { - computer.setID(this.m_computerID); + if( computer != null ) + { + computer.setID( this.m_computerID ); } this.markDirty(); } @Override - public final String getLabel() { + public final String getLabel() + { return this.label; } // Networking stuff @Override - public final void setLabel(String label) { - if (this.getWorld().isClient || Objects.equals(this.label, label)) { + public final void setLabel( String label ) + { + if( this.getWorld().isClient || Objects.equals( this.label, label ) ) + { return; } this.label = label; ServerComputer computer = this.getServerComputer(); - if (computer != null) { - computer.setLabel(label); + if( computer != null ) + { + computer.setLabel( label ); } this.markDirty(); } @Override - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.family; } - protected void transferStateFrom(TileComputerBase copy) { - if (copy.m_computerID != this.m_computerID || copy.m_instanceID != this.m_instanceID) { + protected void transferStateFrom( TileComputerBase copy ) + { + if( copy.m_computerID != this.m_computerID || copy.m_instanceID != this.m_instanceID ) + { this.unload(); this.m_instanceID = copy.m_instanceID; this.m_computerID = copy.m_computerID; @@ -409,39 +475,45 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { - return new ComputerPeripheral("computer", this.createProxy()); + public IPeripheral getPeripheral( Direction side ) + { + return new ComputerPeripheral( "computer", this.createProxy() ); } public abstract ComputerProxy createProxy(); @Nonnull @Override - public Text getName() { - return this.hasCustomName() ? new LiteralText(this.label) : new TranslatableText(this.getCachedState().getBlock() - .getTranslationKey()); + public Text getName() + { + return this.hasCustomName() ? new LiteralText( this.label ) : new TranslatableText( this.getCachedState().getBlock() + .getTranslationKey() ); } @Override - public boolean hasCustomName() { - return !Strings.isNullOrEmpty(this.label); + public boolean hasCustomName() + { + return !Strings.isNullOrEmpty( this.label ); } @Nonnull @Override - public Text getDisplayName() { + public Text getDisplayName() + { return Nameable.super.getDisplayName(); } @Nullable @Override - public Text getCustomName() { - return this.hasCustomName() ? new LiteralText(this.label) : null; + public Text getCustomName() + { + return this.hasCustomName() ? new LiteralText( this.label ) : null; } @Override - public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) { - packetByteBuf.writeInt(this.getServerComputer().getInstanceID()); - packetByteBuf.writeEnumConstant(this.getServerComputer().getFamily()); + public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf ) + { + packetByteBuf.writeInt( this.getServerComputer().getInstanceID() ); + packetByteBuf.writeEnumConstant( this.getServerComputer().getFamily() ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java index 46dd11e1c..dece0c369 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java @@ -8,15 +8,11 @@ package dan200.computercraft.shared.computer.core; import dan200.computercraft.shared.common.ClientTerminal; import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.network.server.ComputerActionServerMessage; -import dan200.computercraft.shared.network.server.KeyEventServerMessage; -import dan200.computercraft.shared.network.server.MouseEventServerMessage; -import dan200.computercraft.shared.network.server.QueueEventServerMessage; -import dan200.computercraft.shared.network.server.RequestComputerMessage; - +import dan200.computercraft.shared.network.server.*; import net.minecraft.nbt.CompoundTag; -public class ClientComputer extends ClientTerminal implements IComputer { +public class ClientComputer extends ClientTerminal implements IComputer +{ private final int m_instanceID; private boolean m_on = false; @@ -24,94 +20,111 @@ public class ClientComputer extends ClientTerminal implements IComputer { private CompoundTag m_userData = null; - public ClientComputer(int instanceID) { - super(false); + public ClientComputer( int instanceID ) + { + super( false ); this.m_instanceID = instanceID; } - public CompoundTag getUserData() { + public CompoundTag getUserData() + { return this.m_userData; } - public void requestState() { + public void requestState() + { // Request state from server - NetworkHandler.sendToServer(new RequestComputerMessage(this.getInstanceID())); + NetworkHandler.sendToServer( new RequestComputerMessage( this.getInstanceID() ) ); } // IComputer @Override - public int getInstanceID() { + public int getInstanceID() + { return this.m_instanceID; } @Override - public void turnOn() { + public void turnOn() + { // Send turnOn to server - NetworkHandler.sendToServer(new ComputerActionServerMessage(this.m_instanceID, ComputerActionServerMessage.Action.TURN_ON)); + NetworkHandler.sendToServer( new ComputerActionServerMessage( this.m_instanceID, ComputerActionServerMessage.Action.TURN_ON ) ); } @Override - public void shutdown() { + public void shutdown() + { // Send shutdown to server - NetworkHandler.sendToServer(new ComputerActionServerMessage(this.m_instanceID, ComputerActionServerMessage.Action.SHUTDOWN)); + NetworkHandler.sendToServer( new ComputerActionServerMessage( this.m_instanceID, ComputerActionServerMessage.Action.SHUTDOWN ) ); } @Override - public void reboot() { + public void reboot() + { // Send reboot to server - NetworkHandler.sendToServer(new ComputerActionServerMessage(this.m_instanceID, ComputerActionServerMessage.Action.REBOOT)); + NetworkHandler.sendToServer( new ComputerActionServerMessage( this.m_instanceID, ComputerActionServerMessage.Action.REBOOT ) ); } @Override - public void queueEvent(String event, Object[] arguments) { + public void queueEvent( String event, Object[] arguments ) + { // Send event to server - NetworkHandler.sendToServer(new QueueEventServerMessage(this.m_instanceID, event, arguments)); + NetworkHandler.sendToServer( new QueueEventServerMessage( this.m_instanceID, event, arguments ) ); } @Override - public boolean isOn() { + public boolean isOn() + { return this.m_on; } @Override - public boolean isCursorDisplayed() { + public boolean isCursorDisplayed() + { return this.m_on && this.m_blinking; } @Override - public void keyDown(int key, boolean repeat) { - NetworkHandler.sendToServer(new KeyEventServerMessage(this.m_instanceID, - repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, - key)); + public void keyDown( int key, boolean repeat ) + { + NetworkHandler.sendToServer( new KeyEventServerMessage( this.m_instanceID, + repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, + key ) ); } @Override - public void keyUp(int key) { - NetworkHandler.sendToServer(new KeyEventServerMessage(this.m_instanceID, KeyEventServerMessage.TYPE_UP, key)); + public void keyUp( int key ) + { + NetworkHandler.sendToServer( new KeyEventServerMessage( this.m_instanceID, KeyEventServerMessage.TYPE_UP, key ) ); } @Override - public void mouseClick(int button, int x, int y) { - NetworkHandler.sendToServer(new MouseEventServerMessage(this.m_instanceID, MouseEventServerMessage.TYPE_CLICK, button, x, y)); + public void mouseClick( int button, int x, int y ) + { + NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_CLICK, button, x, y ) ); } @Override - public void mouseUp(int button, int x, int y) { - NetworkHandler.sendToServer(new MouseEventServerMessage(this.m_instanceID, MouseEventServerMessage.TYPE_UP, button, x, y)); + public void mouseUp( int button, int x, int y ) + { + NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_UP, button, x, y ) ); } @Override - public void mouseDrag(int button, int x, int y) { - NetworkHandler.sendToServer(new MouseEventServerMessage(this.m_instanceID, MouseEventServerMessage.TYPE_DRAG, button, x, y)); + public void mouseDrag( int button, int x, int y ) + { + NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_DRAG, button, x, y ) ); } @Override - public void mouseScroll(int direction, int x, int y) { - NetworkHandler.sendToServer(new MouseEventServerMessage(this.m_instanceID, MouseEventServerMessage.TYPE_SCROLL, direction, x, y)); + public void mouseScroll( int direction, int x, int y ) + { + NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_SCROLL, direction, x, y ) ); } - public void setState(ComputerState state, CompoundTag userData) { + public void setState( ComputerState state, CompoundTag userData ) + { this.m_on = state != ComputerState.OFF; this.m_blinking = state == ComputerState.BLINKING; this.m_userData = userData; diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java index b2b8efba5..725a8c7a5 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java @@ -6,10 +6,12 @@ package dan200.computercraft.shared.computer.core; -public class ClientComputerRegistry extends ComputerRegistry { +public class ClientComputerRegistry extends ComputerRegistry +{ @Override - public void add(int instanceID, ClientComputer computer) { - super.add(instanceID, computer); + public void add( int instanceID, ClientComputer computer ) + { + super.add( instanceID, computer ); computer.requestState(); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java b/src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java index 8ca1124b5..5964b3dbd 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java @@ -6,6 +6,7 @@ package dan200.computercraft.shared.computer.core; -public enum ComputerFamily { +public enum ComputerFamily +{ NORMAL, ADVANCED, COMMAND } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java b/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java index 7a035c2ba..bc80c4cae 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java @@ -11,56 +11,69 @@ import java.util.HashMap; import java.util.Map; import java.util.Random; -public class ComputerRegistry { +public class ComputerRegistry +{ private Map m_computers; private int m_nextUnusedInstanceID; private int m_sessionID; - protected ComputerRegistry() { + protected ComputerRegistry() + { this.m_computers = new HashMap<>(); this.reset(); } - public void reset() { + public void reset() + { this.m_computers.clear(); this.m_nextUnusedInstanceID = 0; this.m_sessionID = new Random().nextInt(); } - public int getSessionID() { + public int getSessionID() + { return this.m_sessionID; } - public int getUnusedInstanceID() { + public int getUnusedInstanceID() + { return this.m_nextUnusedInstanceID++; } - public Collection getComputers() { + public Collection getComputers() + { return this.m_computers.values(); } - public T get(int instanceID) { - if (instanceID >= 0) { - if (this.m_computers.containsKey(instanceID)) { - return this.m_computers.get(instanceID); + public T get( int instanceID ) + { + if( instanceID >= 0 ) + { + if( this.m_computers.containsKey( instanceID ) ) + { + return this.m_computers.get( instanceID ); } } return null; } - public boolean contains(int instanceID) { - return this.m_computers.containsKey(instanceID); + public boolean contains( int instanceID ) + { + return this.m_computers.containsKey( instanceID ); } - public void add(int instanceID, T computer) { - if (this.m_computers.containsKey(instanceID)) { - this.remove(instanceID); + public void add( int instanceID, T computer ) + { + if( this.m_computers.containsKey( instanceID ) ) + { + this.remove( instanceID ); } - this.m_computers.put(instanceID, computer); - this.m_nextUnusedInstanceID = Math.max(this.m_nextUnusedInstanceID, instanceID + 1); + this.m_computers.put( instanceID, computer ); + this.m_nextUnusedInstanceID = Math.max( this.m_nextUnusedInstanceID, instanceID + 1 ); } - public void remove(int instanceID) { - this.m_computers.remove(instanceID); + public void remove( int instanceID ) + { + this.m_computers.remove( instanceID ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ComputerState.java b/src/main/java/dan200/computercraft/shared/computer/core/ComputerState.java index f45b03be9..59c48797f 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ComputerState.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ComputerState.java @@ -6,27 +6,31 @@ package dan200.computercraft.shared.computer.core; -import javax.annotation.Nonnull; - import net.minecraft.util.StringIdentifiable; -public enum ComputerState implements StringIdentifiable { - OFF("off"), ON("on"), BLINKING("blinking"); +import javax.annotation.Nonnull; + +public enum ComputerState implements StringIdentifiable +{ + OFF( "off" ), ON( "on" ), BLINKING( "blinking" ); private final String name; - ComputerState(String name) { + ComputerState( String name ) + { this.name = name; } @Nonnull @Override - public String asString() { + public String asString() + { return this.name; } @Override - public String toString() { + public String toString() + { return this.name; } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/IComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/IComputer.java index 67481a857..0a119990c 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/IComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/IComputer.java @@ -8,7 +8,8 @@ package dan200.computercraft.shared.computer.core; import dan200.computercraft.shared.common.ITerminal; -public interface IComputer extends ITerminal, InputHandler { +public interface IComputer extends ITerminal, InputHandler +{ int getInstanceID(); void turnOn(); @@ -17,15 +18,18 @@ public interface IComputer extends ITerminal, InputHandler { void reboot(); - default void queueEvent(String event) { - this.queueEvent(event, null); + default void queueEvent( String event ) + { + this.queueEvent( event, null ); } @Override - void queueEvent(String event, Object[] arguments); + void queueEvent( String event, Object[] arguments ); - default ComputerState getState() { - if (!this.isOn()) { + default ComputerState getState() + { + if( !this.isOn() ) + { return ComputerState.OFF; } return this.isCursorDisplayed() ? ComputerState.BLINKING : ComputerState.ON; diff --git a/src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java index 249a18c09..b25eae0a0 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java @@ -13,7 +13,8 @@ import javax.annotation.Nullable; * An instance of {@link Container} which provides a computer. You should implement this if you provide custom computers/GUIs to interact with them. */ @FunctionalInterface -public interface IContainerComputer { +public interface IContainerComputer +{ /** * Get the computer you are interacting with. * @@ -30,7 +31,8 @@ public interface IContainerComputer { * @return This container's input. */ @Nonnull - default InputState getInput() { - return new InputState(this); + default InputState getInput() + { + return new InputState( this ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java b/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java index 7accc2e1c..7cc9bd2ba 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java @@ -12,54 +12,61 @@ package dan200.computercraft.shared.computer.core; * @see InputState * @see IComputer */ -public interface InputHandler { - default void keyDown(int key, boolean repeat) { - this.queueEvent("key", - new Object[] { - key, - repeat - }); +public interface InputHandler +{ + default void keyDown( int key, boolean repeat ) + { + this.queueEvent( "key", + new Object[] { + key, + repeat + } ); } - void queueEvent(String event, Object[] arguments); + void queueEvent( String event, Object[] arguments ); - default void keyUp(int key) { - this.queueEvent("key_up", new Object[] {key}); + default void keyUp( int key ) + { + this.queueEvent( "key_up", new Object[] { key } ); } - default void mouseClick(int button, int x, int y) { - this.queueEvent("mouse_click", - new Object[] { - button, - x, - y - }); + default void mouseClick( int button, int x, int y ) + { + this.queueEvent( "mouse_click", + new Object[] { + button, + x, + y + } ); } - default void mouseUp(int button, int x, int y) { - this.queueEvent("mouse_up", - new Object[] { - button, - x, - y - }); + default void mouseUp( int button, int x, int y ) + { + this.queueEvent( "mouse_up", + new Object[] { + button, + x, + y + } ); } - default void mouseDrag(int button, int x, int y) { - this.queueEvent("mouse_drag", - new Object[] { - button, - x, - y - }); + default void mouseDrag( int button, int x, int y ) + { + this.queueEvent( "mouse_drag", + new Object[] { + button, + x, + y + } ); } - default void mouseScroll(int direction, int x, int y) { - this.queueEvent("mouse_scroll", - new Object[] { - direction, - x, - y - }); + default void mouseScroll( int direction, int x, int y ) + { + this.queueEvent( "mouse_scroll", + new Object[] { + direction, + x, + y + } ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/InputState.java b/src/main/java/dan200/computercraft/shared/computer/core/InputState.java index aff2367f6..d5af8608e 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/InputState.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/InputState.java @@ -13,101 +13,121 @@ import it.unimi.dsi.fastutil.ints.IntSet; /** * An {@link InputHandler} which keeps track of the current key and mouse state, and releases them when the container is closed. */ -public class InputState implements InputHandler { +public class InputState implements InputHandler +{ private final IContainerComputer owner; - private final IntSet keysDown = new IntOpenHashSet(4); + private final IntSet keysDown = new IntOpenHashSet( 4 ); private int lastMouseX; private int lastMouseY; private int lastMouseDown = -1; - public InputState(IContainerComputer owner) { + public InputState( IContainerComputer owner ) + { this.owner = owner; } @Override - public void queueEvent(String event, Object[] arguments) { + public void queueEvent( String event, Object[] arguments ) + { IComputer computer = this.owner.getComputer(); - if (computer != null) { - computer.queueEvent(event, arguments); + if( computer != null ) + { + computer.queueEvent( event, arguments ); } } @Override - public void keyDown(int key, boolean repeat) { - this.keysDown.add(key); + public void keyDown( int key, boolean repeat ) + { + this.keysDown.add( key ); IComputer computer = this.owner.getComputer(); - if (computer != null) { - computer.keyDown(key, repeat); + if( computer != null ) + { + computer.keyDown( key, repeat ); } } @Override - public void keyUp(int key) { - this.keysDown.remove(key); + public void keyUp( int key ) + { + this.keysDown.remove( key ); IComputer computer = this.owner.getComputer(); - if (computer != null) { - computer.keyUp(key); + if( computer != null ) + { + computer.keyUp( key ); } } @Override - public void mouseClick(int button, int x, int y) { + public void mouseClick( int button, int x, int y ) + { this.lastMouseX = x; this.lastMouseY = y; this.lastMouseDown = button; IComputer computer = this.owner.getComputer(); - if (computer != null) { - computer.mouseClick(button, x, y); + if( computer != null ) + { + computer.mouseClick( button, x, y ); } } @Override - public void mouseUp(int button, int x, int y) { + public void mouseUp( int button, int x, int y ) + { this.lastMouseX = x; this.lastMouseY = y; this.lastMouseDown = -1; IComputer computer = this.owner.getComputer(); - if (computer != null) { - computer.mouseUp(button, x, y); + if( computer != null ) + { + computer.mouseUp( button, x, y ); } } @Override - public void mouseDrag(int button, int x, int y) { + public void mouseDrag( int button, int x, int y ) + { this.lastMouseX = x; this.lastMouseY = y; this.lastMouseDown = button; IComputer computer = this.owner.getComputer(); - if (computer != null) { - computer.mouseDrag(button, x, y); + if( computer != null ) + { + computer.mouseDrag( button, x, y ); } } @Override - public void mouseScroll(int direction, int x, int y) { + public void mouseScroll( int direction, int x, int y ) + { this.lastMouseX = x; this.lastMouseY = y; IComputer computer = this.owner.getComputer(); - if (computer != null) { - computer.mouseScroll(direction, x, y); + if( computer != null ) + { + computer.mouseScroll( direction, x, y ); } } - public void close() { + public void close() + { IComputer computer = this.owner.getComputer(); - if (computer != null) { + if( computer != null ) + { IntIterator keys = this.keysDown.iterator(); - while (keys.hasNext()) { - computer.keyUp(keys.nextInt()); + while( keys.hasNext() ) + { + computer.keyUp( keys.nextInt() ); } - if (this.lastMouseDown != -1) { - computer.mouseUp(this.lastMouseDown, this.lastMouseX, this.lastMouseY); + if( this.lastMouseDown != -1 ) + { + computer.mouseUp( this.lastMouseDown, this.lastMouseX, this.lastMouseY ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java index cc4b1a7fa..f5c23375d 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.computer.core; -import java.io.InputStream; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraftAPIImpl; import dan200.computercraft.api.ComputerCraftAPI; @@ -29,7 +24,6 @@ import dan200.computercraft.shared.network.client.ComputerDataClientMessage; import dan200.computercraft.shared.network.client.ComputerDeletedClientMessage; import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage; import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.screen.ScreenHandler; @@ -37,7 +31,12 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class ServerComputer extends ServerTerminal implements IComputer, IComputerEnvironment { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.InputStream; + +public class ServerComputer extends ServerTerminal implements IComputer, IComputerEnvironment +{ private final int m_instanceID; private final ComputerFamily m_family; private final Computer m_computer; @@ -49,16 +48,17 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput private boolean m_changedLastFrame; private int m_ticksSincePing; - public ServerComputer(World world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight) { - super(family != ComputerFamily.NORMAL, terminalWidth, terminalHeight); + public ServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight ) + { + super( family != ComputerFamily.NORMAL, terminalWidth, terminalHeight ); this.m_instanceID = instanceID; this.m_world = world; this.m_position = null; this.m_family = family; - this.m_computer = new Computer(this, this.getTerminal(), computerID); - this.m_computer.setLabel(label); + this.m_computer = new Computer( this, this.getTerminal(), computerID ); + this.m_computer.setLabel( label ); this.m_userData = null; this.m_changed = false; @@ -66,36 +66,44 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput this.m_ticksSincePing = 0; } - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.m_family; } - public World getWorld() { + public World getWorld() + { return this.m_world; } - public void setWorld(World world) { + public void setWorld( World world ) + { this.m_world = world; } - public BlockPos getPosition() { + public BlockPos getPosition() + { return this.m_position; } - public void setPosition(BlockPos pos) { - this.m_position = new BlockPos(pos); + public void setPosition( BlockPos pos ) + { + this.m_position = new BlockPos( pos ); } - public IAPIEnvironment getAPIEnvironment() { + public IAPIEnvironment getAPIEnvironment() + { return this.m_computer.getAPIEnvironment(); } - public Computer getComputer() { + public Computer getComputer() + { return this.m_computer; } @Override - public void update() { + public void update() + { super.update(); this.m_computer.tick(); @@ -105,81 +113,102 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput this.m_ticksSincePing++; } - public void keepAlive() { + public void keepAlive() + { this.m_ticksSincePing = 0; } - public boolean hasTimedOut() { + public boolean hasTimedOut() + { return this.m_ticksSincePing > 100; } - public void unload() { + public void unload() + { this.m_computer.unload(); } - public CompoundTag getUserData() { - if (this.m_userData == null) { + public CompoundTag getUserData() + { + if( this.m_userData == null ) + { this.m_userData = new CompoundTag(); } return this.m_userData; } - public void updateUserData() { + public void updateUserData() + { this.m_changed = true; } - public void broadcastState(boolean force) { - if (this.hasOutputChanged() || force) { + public void broadcastState( boolean force ) + { + if( this.hasOutputChanged() || force ) + { // Send computer state to all clients MinecraftServer server = GameInstanceUtils.getServer(); - if (server != null) { - NetworkHandler.sendToAllPlayers(server, this.createComputerPacket()); + if( server != null ) + { + NetworkHandler.sendToAllPlayers( server, this.createComputerPacket() ); } } - if (this.hasTerminalChanged() || force) { + if( this.hasTerminalChanged() || force ) + { MinecraftServer server = GameInstanceUtils.getServer(); - if (server != null) { + if( server != null ) + { // Send terminal state to clients who are currently interacting with the computer. NetworkMessage packet = null; - for (PlayerEntity player : server.getPlayerManager() - .getPlayerList()) { - if (this.isInteracting(player)) { - if (packet == null) { + for( PlayerEntity player : server.getPlayerManager() + .getPlayerList() ) + { + if( this.isInteracting( player ) ) + { + if( packet == null ) + { packet = this.createTerminalPacket(); } - NetworkHandler.sendToPlayer(player, packet); + NetworkHandler.sendToPlayer( player, packet ); } } } } } - public boolean hasOutputChanged() { + public boolean hasOutputChanged() + { return this.m_changedLastFrame; } - private NetworkMessage createComputerPacket() { - return new ComputerDataClientMessage(this); + private NetworkMessage createComputerPacket() + { + return new ComputerDataClientMessage( this ); } - protected boolean isInteracting(PlayerEntity player) { - return this.getContainer(player) != null; + protected boolean isInteracting( PlayerEntity player ) + { + return this.getContainer( player ) != null; } - protected NetworkMessage createTerminalPacket() { - return new ComputerTerminalClientMessage(this.getInstanceID(), this.write()); + protected NetworkMessage createTerminalPacket() + { + return new ComputerTerminalClientMessage( this.getInstanceID(), this.write() ); } @Nullable - public IContainerComputer getContainer(PlayerEntity player) { - if (player == null) { + public IContainerComputer getContainer( PlayerEntity player ) + { + if( player == null ) + { return null; } ScreenHandler container = player.currentScreenHandler; - if (!(container instanceof IContainerComputer)) { + if( !(container instanceof IContainerComputer) ) + { return null; } @@ -188,12 +217,14 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput } @Override - public int getInstanceID() { + public int getInstanceID() + { return this.m_instanceID; } @Override - public void turnOn() { + public void turnOn() + { // Turn on this.m_computer.turnOn(); } @@ -201,147 +232,176 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput // IComputer @Override - public void shutdown() { + public void shutdown() + { // Shutdown this.m_computer.shutdown(); } @Override - public void reboot() { + public void reboot() + { // Reboot this.m_computer.reboot(); } @Override - public void queueEvent(String event, Object[] arguments) { + public void queueEvent( String event, Object[] arguments ) + { // Queue event - this.m_computer.queueEvent(event, arguments); + this.m_computer.queueEvent( event, arguments ); } @Override - public boolean isOn() { + public boolean isOn() + { return this.m_computer.isOn(); } @Override - public boolean isCursorDisplayed() { + public boolean isCursorDisplayed() + { return this.m_computer.isOn() && this.m_computer.isBlinking(); } - public void sendComputerState(PlayerEntity player) { + public void sendComputerState( PlayerEntity player ) + { // Send state to client - NetworkHandler.sendToPlayer(player, this.createComputerPacket()); + NetworkHandler.sendToPlayer( player, this.createComputerPacket() ); } - public void sendTerminalState(PlayerEntity player) { + public void sendTerminalState( PlayerEntity player ) + { // Send terminal state to client - NetworkHandler.sendToPlayer(player, this.createTerminalPacket()); + NetworkHandler.sendToPlayer( player, this.createTerminalPacket() ); } - public void broadcastDelete() { + public void broadcastDelete() + { // Send deletion to client MinecraftServer server = GameInstanceUtils.getServer(); - if (server != null) { - NetworkHandler.sendToAllPlayers(server, new ComputerDeletedClientMessage(this.getInstanceID())); + if( server != null ) + { + NetworkHandler.sendToAllPlayers( server, new ComputerDeletedClientMessage( this.getInstanceID() ) ); } } - public int getID() { + public int getID() + { return this.m_computer.getID(); } - public void setID(int id) { - this.m_computer.setID(id); + public void setID( int id ) + { + this.m_computer.setID( id ); } - public String getLabel() { + public String getLabel() + { return this.m_computer.getLabel(); } - public void setLabel(String label) { - this.m_computer.setLabel(label); + public void setLabel( String label ) + { + this.m_computer.setLabel( label ); } - public int getRedstoneOutput(ComputerSide side) { + public int getRedstoneOutput( ComputerSide side ) + { return this.m_computer.getEnvironment() - .getExternalRedstoneOutput(side); + .getExternalRedstoneOutput( side ); } - public void setRedstoneInput(ComputerSide side, int level) { + public void setRedstoneInput( ComputerSide side, int level ) + { this.m_computer.getEnvironment() - .setRedstoneInput(side, level); + .setRedstoneInput( side, level ); } - public int getBundledRedstoneOutput(ComputerSide side) { + public int getBundledRedstoneOutput( ComputerSide side ) + { return this.m_computer.getEnvironment() - .getExternalBundledRedstoneOutput(side); + .getExternalBundledRedstoneOutput( side ); } - public void setBundledRedstoneInput(ComputerSide side, int combination) { + public void setBundledRedstoneInput( ComputerSide side, int combination ) + { this.m_computer.getEnvironment() - .setBundledRedstoneInput(side, combination); + .setBundledRedstoneInput( side, combination ); } - public void addAPI(ILuaAPI api) { - this.m_computer.addApi(api); + public void addAPI( ILuaAPI api ) + { + this.m_computer.addApi( api ); } // IComputerEnvironment implementation - public void setPeripheral(ComputerSide side, IPeripheral peripheral) { + public void setPeripheral( ComputerSide side, IPeripheral peripheral ) + { this.m_computer.getEnvironment() - .setPeripheral(side, peripheral); + .setPeripheral( side, peripheral ); } - public IPeripheral getPeripheral(ComputerSide side) { + public IPeripheral getPeripheral( ComputerSide side ) + { return this.m_computer.getEnvironment() - .getPeripheral(side); + .getPeripheral( side ); } @Override - public int getDay() { + public int getDay() + { return (int) ((this.m_world.getTimeOfDay() + 6000) / 24000) + 1; } @Override - public double getTimeOfDay() { + public double getTimeOfDay() + { return (this.m_world.getTimeOfDay() + 6000) % 24000 / 1000.0; } @Override - public long getComputerSpaceLimit() { + public long getComputerSpaceLimit() + { return ComputerCraft.computerSpaceLimit; } @Nonnull @Override - public String getHostString() { - return String.format("ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), "1.16.4"); + public String getHostString() + { + return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), "1.16.4" ); } @Nonnull @Override - public String getUserAgent() { + public String getUserAgent() + { return ComputerCraft.MOD_ID + "/" + ComputerCraftAPI.getInstalledVersion(); } @Override - public int assignNewID() { - return ComputerCraftAPI.createUniqueNumberedSaveDir(this.m_world, "computer"); + public int assignNewID() + { + return ComputerCraftAPI.createUniqueNumberedSaveDir( this.m_world, "computer" ); } @Override - public IWritableMount createSaveDirMount(String subPath, long capacity) { - return ComputerCraftAPI.createSaveDirMount(this.m_world, subPath, capacity); + public IWritableMount createSaveDirMount( String subPath, long capacity ) + { + return ComputerCraftAPI.createSaveDirMount( this.m_world, subPath, capacity ); } @Override - public IMount createResourceMount(String domain, String subPath) { - return ComputerCraftAPI.createResourceMount(domain, subPath); + public IMount createResourceMount( String domain, String subPath ) + { + return ComputerCraftAPI.createResourceMount( domain, subPath ); } @Override - public InputStream createResourceFile(String domain, String subPath) { - return ComputerCraftAPIImpl.getResourceFile(domain, subPath); + public InputStream createResourceFile( String domain, String subPath ) + { + return ComputerCraftAPIImpl.getResourceFile( domain, subPath ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java index fa90ad956..2cdcf4052 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java @@ -8,30 +8,39 @@ package dan200.computercraft.shared.computer.core; import java.util.Iterator; -public class ServerComputerRegistry extends ComputerRegistry { - public void update() { +public class ServerComputerRegistry extends ComputerRegistry +{ + public void update() + { Iterator it = this.getComputers().iterator(); - while (it.hasNext()) { + while( it.hasNext() ) + { ServerComputer computer = it.next(); - if (computer.hasTimedOut()) { + if( computer.hasTimedOut() ) + { //System.out.println( "TIMED OUT SERVER COMPUTER " + computer.getInstanceID() ); computer.unload(); computer.broadcastDelete(); it.remove(); //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); - } else { + } + else + { computer.update(); - if (computer.hasTerminalChanged() || computer.hasOutputChanged()) { - computer.broadcastState(false); + if( computer.hasTerminalChanged() || computer.hasOutputChanged() ) + { + computer.broadcastState( false ); } } } } @Override - public void reset() { + public void reset() + { //System.out.println( "RESET SERVER COMPUTERS" ); - for (ServerComputer computer : this.getComputers()) { + for( ServerComputer computer : this.getComputers() ) + { computer.unload(); } super.reset(); @@ -39,32 +48,39 @@ public class ServerComputerRegistry extends ComputerRegistry { } @Override - public void add(int instanceID, ServerComputer computer) { + public void add( int instanceID, ServerComputer computer ) + { //System.out.println( "ADD SERVER COMPUTER " + instanceID ); - super.add(instanceID, computer); - computer.broadcastState(true); + super.add( instanceID, computer ); + computer.broadcastState( true ); //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); } @Override - public void remove(int instanceID) { + public void remove( int instanceID ) + { //System.out.println( "REMOVE SERVER COMPUTER " + instanceID ); - ServerComputer computer = this.get(instanceID); - if (computer != null) { + ServerComputer computer = this.get( instanceID ); + if( computer != null ) + { computer.unload(); computer.broadcastDelete(); } - super.remove(instanceID); + super.remove( instanceID ); //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); } - public ServerComputer lookup(int computerID) { - if (computerID < 0) { + public ServerComputer lookup( int computerID ) + { + if( computerID < 0 ) + { return null; } - for (ServerComputer computer : this.getComputers()) { - if (computer.getID() == computerID) { + for( ServerComputer computer : this.getComputers() ) + { + if( computer.getID() == computerID ) + { return computer; } } diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java index d7ae8eed1..f4202bbe1 100644 --- a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java @@ -8,16 +8,18 @@ package dan200.computercraft.shared.computer.inventory; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.blocks.TileComputer; - import net.minecraft.entity.player.PlayerInventory; import net.minecraft.network.PacketByteBuf; -public class ContainerComputer extends ContainerComputerBase { - public ContainerComputer(int id, TileComputer tile) { - super(ComputerCraftRegistry.ModContainers.COMPUTER, id, tile::isUsableByPlayer, tile.createServerComputer(), tile.getFamily()); +public class ContainerComputer extends ContainerComputerBase +{ + public ContainerComputer( int id, TileComputer tile ) + { + super( ComputerCraftRegistry.ModContainers.COMPUTER, id, tile::isUsableByPlayer, tile.createServerComputer(), tile.getFamily() ); } - public ContainerComputer(int i, PlayerInventory playerInventory, PacketByteBuf packetByteBuf) { - super(ComputerCraftRegistry.ModContainers.COMPUTER, i, playerInventory, packetByteBuf); + public ContainerComputer( int i, PlayerInventory playerInventory, PacketByteBuf packetByteBuf ) + { + super( ComputerCraftRegistry.ModContainers.COMPUTER, i, playerInventory, packetByteBuf ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java index ed33e7488..1d317d5b4 100644 --- a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java @@ -6,86 +6,91 @@ package dan200.computercraft.shared.computer.inventory; -import java.util.Objects; -import java.util.function.Predicate; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ClientComputer; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.IComputer; -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.InputState; +import dan200.computercraft.shared.computer.core.*; import dan200.computercraft.shared.network.container.ComputerContainerData; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; -public class ContainerComputerBase extends ScreenHandler implements IContainerComputer { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; +import java.util.function.Predicate; + +public class ContainerComputerBase extends ScreenHandler implements IContainerComputer +{ private final Predicate canUse; private final IComputer computer; private final ComputerFamily family; - private final InputState input = new InputState(this); + private final InputState input = new InputState( this ); - protected ContainerComputerBase(ScreenHandlerType type, int id, PlayerInventory player, PacketByteBuf packetByteBuf) { - this(type, - id, - x -> true, - getComputer(player, new ComputerContainerData(new PacketByteBuf(packetByteBuf.copy()))), - new ComputerContainerData(new PacketByteBuf(packetByteBuf.copy())).getFamily()); + protected ContainerComputerBase( ScreenHandlerType type, int id, PlayerInventory player, PacketByteBuf packetByteBuf ) + { + this( type, + id, + x -> true, + getComputer( player, new ComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ) ), + new ComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ).getFamily() ); } - protected ContainerComputerBase(ScreenHandlerType type, int id, Predicate canUse, IComputer computer, - ComputerFamily family) { - super(type, id); + protected ContainerComputerBase( ScreenHandlerType type, int id, Predicate canUse, IComputer computer, + ComputerFamily family ) + { + super( type, id ); this.canUse = canUse; - this.computer = Objects.requireNonNull(computer); + this.computer = Objects.requireNonNull( computer ); this.family = family; } - protected static IComputer getComputer(PlayerInventory player, ComputerContainerData data) { + protected static IComputer getComputer( PlayerInventory player, ComputerContainerData data ) + { int id = data.getInstanceId(); - if (!player.player.world.isClient) { - return ComputerCraft.serverComputerRegistry.get(id); + if( !player.player.world.isClient ) + { + return ComputerCraft.serverComputerRegistry.get( id ); } - ClientComputer computer = ComputerCraft.clientComputerRegistry.get(id); - if (computer == null) { - ComputerCraft.clientComputerRegistry.add(id, computer = new ClientComputer(id)); + ClientComputer computer = ComputerCraft.clientComputerRegistry.get( id ); + if( computer == null ) + { + ComputerCraft.clientComputerRegistry.add( id, computer = new ClientComputer( id ) ); } return computer; } @Nonnull - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.family; } @Nullable @Override - public IComputer getComputer() { + public IComputer getComputer() + { return this.computer; } @Nonnull @Override - public InputState getInput() { + public InputState getInput() + { return this.input; } @Override - public void close(@Nonnull PlayerEntity player) { - super.close(player); + public void close( @Nonnull PlayerEntity player ) + { + super.close( player ); this.input.close(); } @Override - public boolean canUse(@Nonnull PlayerEntity player) { - return this.canUse.test(player); + public boolean canUse( @Nonnull PlayerEntity player ) + { + return this.canUse.test( player ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java index dee003e66..d32722b82 100644 --- a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java @@ -6,8 +6,6 @@ package dan200.computercraft.shared.computer.inventory; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.blocks.TileCommandComputer; @@ -15,42 +13,50 @@ import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.network.container.ViewComputerContainerData; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.network.PacketByteBuf; -public class ContainerViewComputer extends ContainerComputerBase implements IContainerComputer { +import javax.annotation.Nonnull; + +public class ContainerViewComputer extends ContainerComputerBase implements IContainerComputer +{ private final int width; private final int height; - public ContainerViewComputer(int id, ServerComputer computer) { - super(ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player -> canInteractWith(computer, player), computer, computer.getFamily()); + public ContainerViewComputer( int id, ServerComputer computer ) + { + super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player -> canInteractWith( computer, player ), computer, computer.getFamily() ); this.width = this.height = 0; } - public ContainerViewComputer(int id, PlayerInventory player, PacketByteBuf packetByteBuf) { - super(ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player, packetByteBuf); - ViewComputerContainerData data = new ViewComputerContainerData(new PacketByteBuf(packetByteBuf.copy())); + public ContainerViewComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf ) + { + super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player, packetByteBuf ); + ViewComputerContainerData data = new ViewComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ); this.width = data.getWidth(); this.height = data.getHeight(); } - private static boolean canInteractWith(@Nonnull ServerComputer computer, @Nonnull PlayerEntity player) { + private static boolean canInteractWith( @Nonnull ServerComputer computer, @Nonnull PlayerEntity player ) + { // If this computer no longer exists then discard it. - if (ComputerCraft.serverComputerRegistry.get(computer.getInstanceID()) != computer) { + if( ComputerCraft.serverComputerRegistry.get( computer.getInstanceID() ) != computer ) + { return false; } // If we're a command computer then ensure we're in creative - return computer.getFamily() != ComputerFamily.COMMAND || TileCommandComputer.isUsable(player); + return computer.getFamily() != ComputerFamily.COMMAND || TileCommandComputer.isUsable( player ); } - public int getWidth() { + public int getWidth() + { return this.width; } - public int getHeight() { + public int getHeight() + { return this.height; } } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java b/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java index 9f3ce0bfa..b267240c5 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java @@ -6,33 +6,36 @@ package dan200.computercraft.shared.computer.items; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; - import net.minecraft.item.ItemStack; -public final class ComputerItemFactory { +import javax.annotation.Nonnull; + +public final class ComputerItemFactory +{ private ComputerItemFactory() {} @Nonnull - public static ItemStack create(TileComputer tile) { - return create(tile.getComputerID(), tile.getLabel(), tile.getFamily()); + public static ItemStack create( TileComputer tile ) + { + return create( tile.getComputerID(), tile.getLabel(), tile.getFamily() ); } @Nonnull - public static ItemStack create(int id, String label, ComputerFamily family) { - switch (family) { - case NORMAL: - return ComputerCraftRegistry.ModItems.COMPUTER_NORMAL.create(id, label); - case ADVANCED: - return ComputerCraftRegistry.ModItems.COMPUTER_ADVANCED.create(id, label); - case COMMAND: - return ComputerCraftRegistry.ModItems.COMPUTER_COMMAND.create(id, label); - default: - return ItemStack.EMPTY; + public static ItemStack create( int id, String label, ComputerFamily family ) + { + switch( family ) + { + case NORMAL: + return ComputerCraftRegistry.ModItems.COMPUTER_NORMAL.create( id, label ); + case ADVANCED: + return ComputerCraftRegistry.ModItems.COMPUTER_ADVANCED.create( id, label ); + case COMMAND: + return ComputerCraftRegistry.ModItems.COMPUTER_COMMAND.create( id, label ); + default: + return ItemStack.EMPTY; } } } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java index 20fc1add4..1b802e19d 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java @@ -6,27 +6,29 @@ package dan200.computercraft.shared.computer.items; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.core.ComputerFamily; - import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; -public interface IComputerItem { +import javax.annotation.Nonnull; + +public interface IComputerItem +{ String NBT_ID = "ComputerId"; - default int getComputerID(@Nonnull ItemStack stack) { + default int getComputerID( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1; + return nbt != null && nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; } - default String getLabel(@Nonnull ItemStack stack) { + default String getLabel( @Nonnull ItemStack stack ) + { return stack.hasCustomName() ? stack.getName() - .getString() : null; + .getString() : null; } ComputerFamily getFamily(); - ItemStack withFamily(@Nonnull ItemStack stack, @Nonnull ComputerFamily family); + ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ); } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java index 6618b95fe..4b6da8aa2 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java @@ -6,36 +6,42 @@ package dan200.computercraft.shared.computer.items; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.blocks.BlockComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; - import net.minecraft.item.ItemStack; import net.minecraft.text.LiteralText; -public class ItemComputer extends ItemComputerBase { - public ItemComputer(BlockComputer block, Settings settings) { - super(block, settings); +import javax.annotation.Nonnull; + +public class ItemComputer extends ItemComputerBase +{ + public ItemComputer( BlockComputer block, Settings settings ) + { + super( block, settings ); } - public ItemStack create(int id, String label) { - ItemStack result = new ItemStack(this); - if (id >= 0) { + public ItemStack create( int id, String label ) + { + ItemStack result = new ItemStack( this ); + if( id >= 0 ) + { result.getOrCreateTag() - .putInt(NBT_ID, id); + .putInt( NBT_ID, id ); } - if (label != null) { - result.setCustomName(new LiteralText(label)); + if( label != null ) + { + result.setCustomName( new LiteralText( label ) ); } return result; } @Override - public ItemStack withFamily(@Nonnull ItemStack stack, @Nonnull ComputerFamily family) { - ItemStack result = ComputerItemFactory.create(this.getComputerID(stack), null, family); - if (stack.hasCustomName()) { - result.setCustomName(stack.getName()); + public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) + { + ItemStack result = ComputerItemFactory.create( this.getComputerID( stack ), null, family ); + if( stack.hasCustomName() ) + { + result.setCustomName( stack.getName() ); } return result; } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java index 64d0792b4..395ce5b24 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java @@ -6,18 +6,12 @@ package dan200.computercraft.shared.computer.items; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.media.IMedia; import dan200.computercraft.shared.computer.blocks.BlockComputerBase; import dan200.computercraft.shared.computer.core.ComputerFamily; - import net.minecraft.client.item.TooltipContext; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; @@ -27,53 +21,71 @@ import net.minecraft.text.TranslatableText; import net.minecraft.util.Formatting; import net.minecraft.world.World; -public abstract class ItemComputerBase extends BlockItem implements IComputerItem, IMedia { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public abstract class ItemComputerBase extends BlockItem implements IComputerItem, IMedia +{ private final ComputerFamily family; - public ItemComputerBase(BlockComputerBase block, Settings settings) { - super(block, settings); + public ItemComputerBase( BlockComputerBase block, Settings settings ) + { + super( block, settings ); this.family = block.getFamily(); } @Override - public void appendTooltip(@Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, @Nonnull TooltipContext options) { - if (options.isAdvanced() || this.getLabel(stack) == null) { - int id = this.getComputerID(stack); - if (id >= 0) { - list.add(new TranslatableText("gui.computercraft.tooltip.computer_id", id).formatted(Formatting.GRAY)); + public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, @Nonnull TooltipContext options ) + { + if( options.isAdvanced() || this.getLabel( stack ) == null ) + { + int id = this.getComputerID( stack ); + if( id >= 0 ) + { + list.add( new TranslatableText( "gui.computercraft.tooltip.computer_id", id ).formatted( Formatting.GRAY ) ); } } } @Override - public String getLabel(@Nonnull ItemStack stack) { - return IComputerItem.super.getLabel(stack); + public String getLabel( @Nonnull ItemStack stack ) + { + return IComputerItem.super.getLabel( stack ); } @Override - public final ComputerFamily getFamily() { + public final ComputerFamily getFamily() + { return this.family; } // IMedia implementation @Override - public boolean setLabel(@Nonnull ItemStack stack, String label) { - if (label != null) { - stack.setCustomName(new LiteralText(label)); - } else { + public boolean setLabel( @Nonnull ItemStack stack, String label ) + { + if( label != null ) + { + stack.setCustomName( new LiteralText( label ) ); + } + else + { stack.removeCustomName(); } return true; } @Override - public IMount createDataMount(@Nonnull ItemStack stack, @Nonnull World world) { + public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) + { ComputerFamily family = this.getFamily(); - if (family != ComputerFamily.COMMAND) { - int id = this.getComputerID(stack); - if (id >= 0) { - return ComputerCraftAPI.createSaveDirMount(world, "computer/" + id, ComputerCraft.computerSpaceLimit); + if( family != ComputerFamily.COMMAND ) + { + int id = this.getComputerID( stack ); + if( id >= 0 ) + { + return ComputerCraftAPI.createSaveDirMount( world, "computer/" + id, ComputerCraft.computerSpaceLimit ); } } return null; diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java index 5c784728b..07a149301 100644 --- a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java @@ -6,10 +6,7 @@ package dan200.computercraft.shared.computer.recipe; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.items.IComputerItem; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.Ingredient; @@ -18,32 +15,41 @@ import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; +import javax.annotation.Nonnull; + /** * Represents a recipe which converts a computer from one form into another. */ -public abstract class ComputerConvertRecipe extends ShapedRecipe { +public abstract class ComputerConvertRecipe extends ShapedRecipe +{ private final String group; - public ComputerConvertRecipe(Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result) { - super(identifier, group, width, height, ingredients, result); + public ComputerConvertRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result ) + { + super( identifier, group, width, height, ingredients, result ); this.group = group; } @Nonnull @Override - public String getGroup() { + public String getGroup() + { return this.group; } @Override - public boolean matches(@Nonnull CraftingInventory inventory, @Nonnull World world) { - if (!super.matches(inventory, world)) { + public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) + { + if( !super.matches( inventory, world ) ) + { return false; } - for (int i = 0; i < inventory.size(); i++) { - if (inventory.getStack(i) - .getItem() instanceof IComputerItem) { + for( int i = 0; i < inventory.size(); i++ ) + { + if( inventory.getStack( i ) + .getItem() instanceof IComputerItem ) + { return true; } } @@ -53,12 +59,15 @@ public abstract class ComputerConvertRecipe extends ShapedRecipe { @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inventory) { + public ItemStack craft( @Nonnull CraftingInventory inventory ) + { // Find our computer item and convert it. - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStack(i); - if (stack.getItem() instanceof IComputerItem) { - return this.convert((IComputerItem) stack.getItem(), stack); + for( int i = 0; i < inventory.size(); i++ ) + { + ItemStack stack = inventory.getStack( i ); + if( stack.getItem() instanceof IComputerItem ) + { + return this.convert( (IComputerItem) stack.getItem(), stack ); } } @@ -66,5 +75,5 @@ public abstract class ComputerConvertRecipe extends ShapedRecipe { } @Nonnull - protected abstract ItemStack convert(@Nonnull IComputerItem item, @Nonnull ItemStack stack); + protected abstract ItemStack convert( @Nonnull IComputerItem item, @Nonnull ItemStack stack ); } diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java index b6ebb380d..265f2900d 100644 --- a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java @@ -6,12 +6,9 @@ package dan200.computercraft.shared.computer.recipe; -import javax.annotation.Nonnull; - import com.google.gson.JsonObject; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.util.RecipeUtil; - import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.recipe.Ingredient; @@ -20,62 +17,73 @@ import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; import net.minecraft.util.collection.DefaultedList; -public abstract class ComputerFamilyRecipe extends ComputerConvertRecipe { +import javax.annotation.Nonnull; + +public abstract class ComputerFamilyRecipe extends ComputerConvertRecipe +{ private final ComputerFamily family; - public ComputerFamilyRecipe(Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family) { - super(identifier, group, width, height, ingredients, result); + public ComputerFamilyRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, + ComputerFamily family ) + { + super( identifier, group, width, height, ingredients, result ); this.family = family; } - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.family; } - public abstract static class Serializer implements RecipeSerializer { + public abstract static class Serializer implements RecipeSerializer + { @Nonnull @Override - public T read(@Nonnull Identifier identifier, @Nonnull JsonObject json) { - String group = JsonHelper.getString(json, "group", ""); - ComputerFamily family = RecipeUtil.getFamily(json, "family"); + public T read( @Nonnull Identifier identifier, @Nonnull JsonObject json ) + { + String group = JsonHelper.getString( json, "group", "" ); + ComputerFamily family = RecipeUtil.getFamily( json, "family" ); - RecipeUtil.ShapedTemplate template = RecipeUtil.getTemplate(json); - ItemStack result = getItemStack(JsonHelper.getObject(json, "result")); + RecipeUtil.ShapedTemplate template = RecipeUtil.getTemplate( json ); + ItemStack result = getItemStack( JsonHelper.getObject( json, "result" ) ); - return this.create(identifier, group, template.width, template.height, template.ingredients, result, family); + return this.create( identifier, group, template.width, template.height, template.ingredients, result, family ); } - protected abstract T create(Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family); + protected abstract T create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, + ComputerFamily family ); @Nonnull @Override - public T read(@Nonnull Identifier identifier, @Nonnull PacketByteBuf buf) { + public T read( @Nonnull Identifier identifier, @Nonnull PacketByteBuf buf ) + { int width = buf.readVarInt(); int height = buf.readVarInt(); - String group = buf.readString(Short.MAX_VALUE); + String group = buf.readString( Short.MAX_VALUE ); - DefaultedList ingredients = DefaultedList.ofSize(width * height, Ingredient.EMPTY); - for (int i = 0; i < ingredients.size(); i++) { - ingredients.set(i, Ingredient.fromPacket(buf)); + DefaultedList ingredients = DefaultedList.ofSize( width * height, Ingredient.EMPTY ); + for( int i = 0; i < ingredients.size(); i++ ) + { + ingredients.set( i, Ingredient.fromPacket( buf ) ); } ItemStack result = buf.readItemStack(); - ComputerFamily family = buf.readEnumConstant(ComputerFamily.class); - return this.create(identifier, group, width, height, ingredients, result, family); + ComputerFamily family = buf.readEnumConstant( ComputerFamily.class ); + return this.create( identifier, group, width, height, ingredients, result, family ); } @Override - public void write(@Nonnull PacketByteBuf buf, @Nonnull T recipe) { - buf.writeVarInt(recipe.getWidth()); - buf.writeVarInt(recipe.getHeight()); - buf.writeString(recipe.getGroup()); - for (Ingredient ingredient : recipe.getPreviewInputs()) { - ingredient.write(buf); + public void write( @Nonnull PacketByteBuf buf, @Nonnull T recipe ) + { + buf.writeVarInt( recipe.getWidth() ); + buf.writeVarInt( recipe.getHeight() ); + buf.writeString( recipe.getGroup() ); + for( Ingredient ingredient : recipe.getPreviewInputs() ) + { + ingredient.write( buf ); } - buf.writeItemStack(recipe.getOutput()); - buf.writeEnumConstant(recipe.getFamily()); + buf.writeItemStack( recipe.getOutput() ); + buf.writeEnumConstant( recipe.getFamily() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerUpgradeRecipe.java index 669d4fa98..57954114a 100644 --- a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerUpgradeRecipe.java +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerUpgradeRecipe.java @@ -6,41 +6,46 @@ package dan200.computercraft.shared.computer.recipe; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.items.IComputerItem; - import net.minecraft.item.ItemStack; import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.RecipeSerializer; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; -public class ComputerUpgradeRecipe extends ComputerFamilyRecipe { +import javax.annotation.Nonnull; + +public class ComputerUpgradeRecipe extends ComputerFamilyRecipe +{ public static final RecipeSerializer SERIALIZER = - new dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe.Serializer() { - @Override - protected ComputerUpgradeRecipe create(Identifier identifier, String group, int width, int height, DefaultedList ingredients, - ItemStack result, ComputerFamily family) { - return new ComputerUpgradeRecipe(identifier, group, width, height, ingredients, result, family); - } - }; + new dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe.Serializer() + { + @Override + protected ComputerUpgradeRecipe create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, + ItemStack result, ComputerFamily family ) + { + return new ComputerUpgradeRecipe( identifier, group, width, height, ingredients, result, family ); + } + }; - public ComputerUpgradeRecipe(Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family) { - super(identifier, group, width, height, ingredients, result, family); + public ComputerUpgradeRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, + ComputerFamily family ) + { + super( identifier, group, width, height, ingredients, result, family ); } @Nonnull @Override - protected ItemStack convert(@Nonnull IComputerItem item, @Nonnull ItemStack stack) { - return item.withFamily(stack, this.getFamily()); + protected ItemStack convert( @Nonnull IComputerItem item, @Nonnull ItemStack stack ) + { + return item.withFamily( stack, this.getFamily() ); } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } } diff --git a/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java b/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java index 4f95f2e50..ee98295f1 100644 --- a/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java +++ b/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.data; -import java.util.Collections; -import java.util.Set; - -import javax.annotation.Nonnull; - import net.minecraft.block.entity.BlockEntity; import net.minecraft.loot.condition.LootCondition; import net.minecraft.loot.condition.LootConditionType; @@ -19,32 +14,41 @@ import net.minecraft.loot.context.LootContextParameter; import net.minecraft.loot.context.LootContextParameters; import net.minecraft.util.Nameable; +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.Set; + /** * A loot condition which checks if the tile entity has a name. */ -public final class BlockNamedEntityLootCondition implements LootCondition { +public final class BlockNamedEntityLootCondition implements LootCondition +{ public static final BlockNamedEntityLootCondition INSTANCE = new BlockNamedEntityLootCondition(); - public static final LootConditionType TYPE = ConstantLootConditionSerializer.type(INSTANCE); + public static final LootConditionType TYPE = ConstantLootConditionSerializer.type( INSTANCE ); public static final Builder BUILDER = () -> INSTANCE; - private BlockNamedEntityLootCondition() { + private BlockNamedEntityLootCondition() + { } @Override - public boolean test(LootContext lootContext) { - BlockEntity tile = lootContext.get(LootContextParameters.BLOCK_ENTITY); + public boolean test( LootContext lootContext ) + { + BlockEntity tile = lootContext.get( LootContextParameters.BLOCK_ENTITY ); return tile instanceof Nameable && ((Nameable) tile).hasCustomName(); } @Nonnull @Override - public Set> getRequiredParameters() { - return Collections.singleton(LootContextParameters.BLOCK_ENTITY); + public Set> getRequiredParameters() + { + return Collections.singleton( LootContextParameters.BLOCK_ENTITY ); } @Override @Nonnull - public LootConditionType getType() { + public LootConditionType getType() + { return TYPE; } } diff --git a/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java b/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java index 7073b000d..50220fa1c 100644 --- a/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java +++ b/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java @@ -6,34 +6,38 @@ package dan200.computercraft.shared.data; -import javax.annotation.Nonnull; - import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; - import net.minecraft.loot.condition.LootCondition; import net.minecraft.loot.condition.LootConditionType; import net.minecraft.util.JsonSerializer; -public final class ConstantLootConditionSerializer implements JsonSerializer { +import javax.annotation.Nonnull; + +public final class ConstantLootConditionSerializer implements JsonSerializer +{ private final T instance; - public ConstantLootConditionSerializer(T instance) { + public ConstantLootConditionSerializer( T instance ) + { this.instance = instance; } - public static LootConditionType type(T condition) { - return new LootConditionType(new ConstantLootConditionSerializer<>(condition)); + public static LootConditionType type( T condition ) + { + return new LootConditionType( new ConstantLootConditionSerializer<>( condition ) ); } @Override - public void toJson(@Nonnull JsonObject json, @Nonnull T object, @Nonnull JsonSerializationContext context) { + public void toJson( @Nonnull JsonObject json, @Nonnull T object, @Nonnull JsonSerializationContext context ) + { } @Nonnull @Override - public T fromJson(@Nonnull JsonObject json, @Nonnull JsonDeserializationContext context) { + public T fromJson( @Nonnull JsonObject json, @Nonnull JsonDeserializationContext context ) + { return this.instance; } } diff --git a/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java b/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java index 377dc14da..7b2717d29 100644 --- a/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java +++ b/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java @@ -6,13 +6,7 @@ package dan200.computercraft.shared.data; -import java.util.Collections; -import java.util.Set; - -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.blocks.IComputerTile; - import net.minecraft.block.entity.BlockEntity; import net.minecraft.loot.condition.LootCondition; import net.minecraft.loot.condition.LootConditionType; @@ -20,32 +14,41 @@ import net.minecraft.loot.context.LootContext; import net.minecraft.loot.context.LootContextParameter; import net.minecraft.loot.context.LootContextParameters; +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.Set; + /** * A loot condition which checks if the tile entity has has a non-0 ID. */ -public final class HasComputerIdLootCondition implements LootCondition { +public final class HasComputerIdLootCondition implements LootCondition +{ public static final HasComputerIdLootCondition INSTANCE = new HasComputerIdLootCondition(); - public static final LootConditionType TYPE = ConstantLootConditionSerializer.type(INSTANCE); + public static final LootConditionType TYPE = ConstantLootConditionSerializer.type( INSTANCE ); public static final Builder BUILDER = () -> INSTANCE; - private HasComputerIdLootCondition() { + private HasComputerIdLootCondition() + { } @Override - public boolean test(LootContext lootContext) { - BlockEntity tile = lootContext.get(LootContextParameters.BLOCK_ENTITY); + public boolean test( LootContext lootContext ) + { + BlockEntity tile = lootContext.get( LootContextParameters.BLOCK_ENTITY ); return tile instanceof IComputerTile && ((IComputerTile) tile).getComputerID() >= 0; } @Nonnull @Override - public Set> getRequiredParameters() { - return Collections.singleton(LootContextParameters.BLOCK_ENTITY); + public Set> getRequiredParameters() + { + return Collections.singleton( LootContextParameters.BLOCK_ENTITY ); } @Override @Nonnull - public LootConditionType getType() { + public LootConditionType getType() + { return TYPE; } } diff --git a/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java b/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java index 048d092da..e52690853 100644 --- a/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java +++ b/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.data; -import java.util.Collections; -import java.util.Set; - -import javax.annotation.Nonnull; - import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.loot.condition.LootCondition; @@ -19,32 +14,41 @@ import net.minecraft.loot.context.LootContext; import net.minecraft.loot.context.LootContextParameter; import net.minecraft.loot.context.LootContextParameters; +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.Set; + /** * A loot condition which checks if the entity is in creative mode. */ -public final class PlayerCreativeLootCondition implements LootCondition { +public final class PlayerCreativeLootCondition implements LootCondition +{ public static final PlayerCreativeLootCondition INSTANCE = new PlayerCreativeLootCondition(); - public static final LootConditionType TYPE = ConstantLootConditionSerializer.type(INSTANCE); + public static final LootConditionType TYPE = ConstantLootConditionSerializer.type( INSTANCE ); public static final Builder BUILDER = () -> INSTANCE; - private PlayerCreativeLootCondition() { + private PlayerCreativeLootCondition() + { } @Override - public boolean test(LootContext lootContext) { - Entity entity = lootContext.get(LootContextParameters.THIS_ENTITY); + public boolean test( LootContext lootContext ) + { + Entity entity = lootContext.get( LootContextParameters.THIS_ENTITY ); return entity instanceof PlayerEntity && ((PlayerEntity) entity).abilities.creativeMode; } @Nonnull @Override - public Set> getRequiredParameters() { - return Collections.singleton(LootContextParameters.THIS_ENTITY); + public Set> getRequiredParameters() + { + return Collections.singleton( LootContextParameters.THIS_ENTITY ); } @Override @Nonnull - public LootConditionType getType() { + public LootConditionType getType() + { return TYPE; } } diff --git a/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java b/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java index a3d1172d5..1455446c9 100644 --- a/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java +++ b/src/main/java/dan200/computercraft/shared/integration/ModMenuIntegration.java @@ -12,10 +12,12 @@ import net.fabricmc.api.Environment; // A stub modmenu entrypoint for when we get there -@Environment(EnvType.CLIENT) -public class ModMenuIntegration implements ModMenuApi { +@Environment( EnvType.CLIENT ) +public class ModMenuIntegration implements ModMenuApi +{ @Override - public ConfigScreenFactory getModConfigScreenFactory() { + public ConfigScreenFactory getModConfigScreenFactory() + { return parent -> null; } } diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java b/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java index 876ca7122..deeb80c3b 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.media.items; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.IMount; @@ -18,7 +13,6 @@ import dan200.computercraft.api.media.IMedia; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.util.Colour; - import net.minecraft.client.item.TooltipContext; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; @@ -31,83 +25,107 @@ import net.minecraft.util.Formatting; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -public class ItemDisk extends Item implements IMedia, IColouredItem { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ItemDisk extends Item implements IMedia, IColouredItem +{ private static final String NBT_ID = "DiskId"; - public ItemDisk(Settings settings) { - super(settings); + public ItemDisk( Settings settings ) + { + super( settings ); } @Override - public void appendTooltip(@Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, TooltipContext options) { - if (options.isAdvanced()) { - int id = getDiskID(stack); - if (id >= 0) { - list.add(new TranslatableText("gui.computercraft.tooltip.disk_id", id).formatted(Formatting.GRAY)); + public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, TooltipContext options ) + { + if( options.isAdvanced() ) + { + int id = getDiskID( stack ); + if( id >= 0 ) + { + list.add( new TranslatableText( "gui.computercraft.tooltip.disk_id", id ).formatted( Formatting.GRAY ) ); } } } @Override - public void appendStacks(@Nonnull ItemGroup tabs, @Nonnull DefaultedList list) { - if (!this.isIn(tabs)) { + public void appendStacks( @Nonnull ItemGroup tabs, @Nonnull DefaultedList list ) + { + if( !this.isIn( tabs ) ) + { return; } - for (int colour = 0; colour < 16; colour++) { - list.add(createFromIDAndColour(-1, null, Colour.VALUES[colour].getHex())); + for( int colour = 0; colour < 16; colour++ ) + { + list.add( createFromIDAndColour( -1, null, Colour.VALUES[colour].getHex() ) ); } } @Nonnull - public static ItemStack createFromIDAndColour(int id, String label, int colour) { - ItemStack stack = new ItemStack(ComputerCraftRegistry.ModItems.DISK); - setDiskID(stack, id); - ComputerCraftRegistry.ModItems.DISK.setLabel(stack, label); - IColouredItem.setColourBasic(stack, colour); + public static ItemStack createFromIDAndColour( int id, String label, int colour ) + { + ItemStack stack = new ItemStack( ComputerCraftRegistry.ModItems.DISK ); + setDiskID( stack, id ); + ComputerCraftRegistry.ModItems.DISK.setLabel( stack, label ); + IColouredItem.setColourBasic( stack, colour ); return stack; } - private static void setDiskID(@Nonnull ItemStack stack, int id) { - if (id >= 0) { + private static void setDiskID( @Nonnull ItemStack stack, int id ) + { + if( id >= 0 ) + { stack.getOrCreateTag() - .putInt(NBT_ID, id); + .putInt( NBT_ID, id ); } } - public static int getDiskID(@Nonnull ItemStack stack) { + public static int getDiskID( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1; + return nbt != null && nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; } @Override - public String getLabel(@Nonnull ItemStack stack) { + public String getLabel( @Nonnull ItemStack stack ) + { return stack.hasCustomName() ? stack.getName() - .getString() : null; + .getString() : null; } @Override - public boolean setLabel(@Nonnull ItemStack stack, String label) { - if (label != null) { - stack.setCustomName(new LiteralText(label)); - } else { + public boolean setLabel( @Nonnull ItemStack stack, String label ) + { + if( label != null ) + { + stack.setCustomName( new LiteralText( label ) ); + } + else + { stack.removeCustomName(); } return true; } @Override - public IMount createDataMount(@Nonnull ItemStack stack, @Nonnull World world) { - int diskID = getDiskID(stack); - if (diskID < 0) { - diskID = ComputerCraftAPI.createUniqueNumberedSaveDir(world, "disk"); - setDiskID(stack, diskID); + public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) + { + int diskID = getDiskID( stack ); + if( diskID < 0 ) + { + diskID = ComputerCraftAPI.createUniqueNumberedSaveDir( world, "disk" ); + setDiskID( stack, diskID ); } - return ComputerCraftAPI.createSaveDirMount(world, "disk/" + diskID, ComputerCraft.floppySpaceLimit); + return ComputerCraftAPI.createSaveDirMount( world, "disk/" + diskID, ComputerCraft.floppySpaceLimit ); } @Override - public int getColour(@Nonnull ItemStack stack) { - int colour = IColouredItem.getColourBasic(stack); + public int getColour( @Nonnull ItemStack stack ) + { + int colour = IColouredItem.getColourBasic( stack ); return colour == -1 ? Colour.WHITE.getHex() : colour; } } diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java index 4986327cc..480e8c08d 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java @@ -6,14 +6,9 @@ package dan200.computercraft.shared.media.items; -import java.util.List; - -import javax.annotation.Nonnull; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.ContainerHeldItem; import dan200.computercraft.shared.network.container.HeldItemContainerData; - import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; @@ -26,7 +21,11 @@ import net.minecraft.util.Hand; import net.minecraft.util.TypedActionResult; import net.minecraft.world.World; -public class ItemPrintout extends Item { +import javax.annotation.Nonnull; +import java.util.List; + +public class ItemPrintout extends Item +{ public static final int LINES_PER_PAGE = 21; public static final int LINE_MAX_LENGTH = 25; public static final int MAX_PAGES = 16; @@ -36,39 +35,49 @@ public class ItemPrintout extends Item { private static final String NBT_LINE_COLOUR = "Color"; private final Type type; - public ItemPrintout(Settings settings, Type type) { - super(settings); + public ItemPrintout( Settings settings, Type type ) + { + super( settings ); this.type = type; } @Nonnull - public static ItemStack createSingleFromTitleAndText(String title, String[] text, String[] colours) { - return ComputerCraftRegistry.ModItems.PRINTED_PAGE.createFromTitleAndText(title, text, colours); + public static ItemStack createSingleFromTitleAndText( String title, String[] text, String[] colours ) + { + return ComputerCraftRegistry.ModItems.PRINTED_PAGE.createFromTitleAndText( title, text, colours ); } @Nonnull - private ItemStack createFromTitleAndText(String title, String[] text, String[] colours) { - ItemStack stack = new ItemStack(this); + private ItemStack createFromTitleAndText( String title, String[] text, String[] colours ) + { + ItemStack stack = new ItemStack( this ); // Build NBT - if (title != null) { + if( title != null ) + { stack.getOrCreateTag() - .putString(NBT_TITLE, title); + .putString( NBT_TITLE, title ); } - if (text != null) { + if( text != null ) + { CompoundTag tag = stack.getOrCreateTag(); - tag.putInt(NBT_PAGES, text.length / LINES_PER_PAGE); - for (int i = 0; i < text.length; i++) { - if (text[i] != null) { - tag.putString(NBT_LINE_TEXT + i, text[i]); + tag.putInt( NBT_PAGES, text.length / LINES_PER_PAGE ); + for( int i = 0; i < text.length; i++ ) + { + if( text[i] != null ) + { + tag.putString( NBT_LINE_TEXT + i, text[i] ); } } } - if (colours != null) { + if( colours != null ) + { CompoundTag tag = stack.getOrCreateTag(); - for (int i = 0; i < colours.length; i++) { - if (colours[i] != null) { - tag.putString(NBT_LINE_COLOUR + i, colours[i]); + for( int i = 0; i < colours.length; i++ ) + { + if( colours[i] != null ) + { + tag.putString( NBT_LINE_COLOUR + i, colours[i] ); } } } @@ -78,68 +87,82 @@ public class ItemPrintout extends Item { } @Nonnull - public static ItemStack createMultipleFromTitleAndText(String title, String[] text, String[] colours) { - return ComputerCraftRegistry.ModItems.PRINTED_PAGES.createFromTitleAndText(title, text, colours); + public static ItemStack createMultipleFromTitleAndText( String title, String[] text, String[] colours ) + { + return ComputerCraftRegistry.ModItems.PRINTED_PAGES.createFromTitleAndText( title, text, colours ); } @Nonnull - public static ItemStack createBookFromTitleAndText(String title, String[] text, String[] colours) { - return ComputerCraftRegistry.ModItems.PRINTED_BOOK.createFromTitleAndText(title, text, colours); + public static ItemStack createBookFromTitleAndText( String title, String[] text, String[] colours ) + { + return ComputerCraftRegistry.ModItems.PRINTED_BOOK.createFromTitleAndText( title, text, colours ); } - public static String[] getText(@Nonnull ItemStack stack) { - return getLines(stack, NBT_LINE_TEXT); + public static String[] getText( @Nonnull ItemStack stack ) + { + return getLines( stack, NBT_LINE_TEXT ); } - private static String[] getLines(@Nonnull ItemStack stack, String prefix) { + private static String[] getLines( @Nonnull ItemStack stack, String prefix ) + { CompoundTag nbt = stack.getTag(); - int numLines = getPageCount(stack) * LINES_PER_PAGE; + int numLines = getPageCount( stack ) * LINES_PER_PAGE; String[] lines = new String[numLines]; - for (int i = 0; i < lines.length; i++) { - lines[i] = nbt != null ? nbt.getString(prefix + i) : ""; + for( int i = 0; i < lines.length; i++ ) + { + lines[i] = nbt != null ? nbt.getString( prefix + i ) : ""; } return lines; } - public static int getPageCount(@Nonnull ItemStack stack) { + public static int getPageCount( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_PAGES) ? nbt.getInt(NBT_PAGES) : 1; + return nbt != null && nbt.contains( NBT_PAGES ) ? nbt.getInt( NBT_PAGES ) : 1; } - public static String[] getColours(@Nonnull ItemStack stack) { - return getLines(stack, NBT_LINE_COLOUR); + public static String[] getColours( @Nonnull ItemStack stack ) + { + return getLines( stack, NBT_LINE_COLOUR ); } @Nonnull @Override - public TypedActionResult use(World world, @Nonnull PlayerEntity player, @Nonnull Hand hand) { - if (!world.isClient) { - new HeldItemContainerData(hand).open(player, - new ContainerHeldItem.Factory(ComputerCraftRegistry.ModContainers.PRINTOUT, - player.getStackInHand(hand), - hand)); + public TypedActionResult use( World world, @Nonnull PlayerEntity player, @Nonnull Hand hand ) + { + if( !world.isClient ) + { + new HeldItemContainerData( hand ).open( player, + new ContainerHeldItem.Factory( ComputerCraftRegistry.ModContainers.PRINTOUT, + player.getStackInHand( hand ), + hand ) ); } - return new TypedActionResult<>(ActionResult.SUCCESS, player.getStackInHand(hand)); + return new TypedActionResult<>( ActionResult.SUCCESS, player.getStackInHand( hand ) ); } @Override - public void appendTooltip(@Nonnull ItemStack stack, World world, @Nonnull List list, @Nonnull TooltipContext options) { - String title = getTitle(stack); - if (title != null && !title.isEmpty()) { - list.add(new LiteralText(title)); + public void appendTooltip( @Nonnull ItemStack stack, World world, @Nonnull List list, @Nonnull TooltipContext options ) + { + String title = getTitle( stack ); + if( title != null && !title.isEmpty() ) + { + list.add( new LiteralText( title ) ); } } - public static String getTitle(@Nonnull ItemStack stack) { + public static String getTitle( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_TITLE) ? nbt.getString(NBT_TITLE) : null; + return nbt != null && nbt.contains( NBT_TITLE ) ? nbt.getString( NBT_TITLE ) : null; } - public Type getType() { + public Type getType() + { return this.type; } - public enum Type { + public enum Type + { PAGE, PAGES, BOOK } } diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java b/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java index 8a7e76957..7e0783999 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java @@ -6,19 +6,12 @@ package dan200.computercraft.shared.media.items; -import java.io.IOException; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.media.IMedia; import dan200.computercraft.core.filesystem.SubMount; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.util.Colour; - import net.minecraft.client.item.TooltipContext; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; @@ -29,85 +22,113 @@ import net.minecraft.text.Text; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -public class ItemTreasureDisk extends Item implements IMedia { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.List; + +public class ItemTreasureDisk extends Item implements IMedia +{ private static final String NBT_TITLE = "Title"; private static final String NBT_COLOUR = "Colour"; private static final String NBT_SUB_PATH = "SubPath"; - public ItemTreasureDisk(Settings settings) { - super(settings); + public ItemTreasureDisk( Settings settings ) + { + super( settings ); } - public static ItemStack create(String subPath, int colourIndex) { - ItemStack result = new ItemStack(ComputerCraftRegistry.ModItems.TREASURE_DISK); + public static ItemStack create( String subPath, int colourIndex ) + { + ItemStack result = new ItemStack( ComputerCraftRegistry.ModItems.TREASURE_DISK ); CompoundTag nbt = result.getOrCreateTag(); - nbt.putString(NBT_SUB_PATH, subPath); + nbt.putString( NBT_SUB_PATH, subPath ); - int slash = subPath.indexOf('/'); - if (slash >= 0) { - String author = subPath.substring(0, slash); - String title = subPath.substring(slash + 1); - nbt.putString(NBT_TITLE, "\"" + title + "\" by " + author); - } else { - nbt.putString(NBT_TITLE, "untitled"); + int slash = subPath.indexOf( '/' ); + if( slash >= 0 ) + { + String author = subPath.substring( 0, slash ); + String title = subPath.substring( slash + 1 ); + nbt.putString( NBT_TITLE, "\"" + title + "\" by " + author ); } - nbt.putInt(NBT_COLOUR, Colour.values()[colourIndex].getHex()); + else + { + nbt.putString( NBT_TITLE, "untitled" ); + } + nbt.putInt( NBT_COLOUR, Colour.values()[colourIndex].getHex() ); return result; } - public static int getColour(@Nonnull ItemStack stack) { + public static int getColour( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_COLOUR) ? nbt.getInt(NBT_COLOUR) : Colour.BLUE.getHex(); + return nbt != null && nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : Colour.BLUE.getHex(); } @Override - public void appendTooltip(@Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, @Nonnull TooltipContext tooltipOptions) { - String label = getTitle(stack); - if (!label.isEmpty()) { - list.add(new LiteralText(label)); + public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, @Nonnull TooltipContext tooltipOptions ) + { + String label = getTitle( stack ); + if( !label.isEmpty() ) + { + list.add( new LiteralText( label ) ); } } @Override - public void appendStacks(@Nonnull ItemGroup group, @Nonnull DefaultedList stacks) { + public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList stacks ) + { } @Nonnull - private static String getTitle(@Nonnull ItemStack stack) { + private static String getTitle( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_TITLE) ? nbt.getString(NBT_TITLE) : "'alongtimeago' by dan200"; + return nbt != null && nbt.contains( NBT_TITLE ) ? nbt.getString( NBT_TITLE ) : "'alongtimeago' by dan200"; } @Override - public String getLabel(@Nonnull ItemStack stack) { - return getTitle(stack); + public String getLabel( @Nonnull ItemStack stack ) + { + return getTitle( stack ); } @Override - public IMount createDataMount(@Nonnull ItemStack stack, @Nonnull World world) { + public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) + { IMount rootTreasure = getTreasureMount(); - String subPath = getSubPath(stack); - try { - if (rootTreasure.exists(subPath)) { - return new SubMount(rootTreasure, subPath); - } else if (rootTreasure.exists("deprecated/" + subPath)) { - return new SubMount(rootTreasure, "deprecated/" + subPath); - } else { + String subPath = getSubPath( stack ); + try + { + if( rootTreasure.exists( subPath ) ) + { + return new SubMount( rootTreasure, subPath ); + } + else if( rootTreasure.exists( "deprecated/" + subPath ) ) + { + return new SubMount( rootTreasure, "deprecated/" + subPath ); + } + else + { return null; } - } catch (IOException e) { + } + catch( IOException e ) + { return null; } } - private static IMount getTreasureMount() { - return ComputerCraftAPI.createResourceMount("computercraft", "lua/treasure"); + private static IMount getTreasureMount() + { + return ComputerCraftAPI.createResourceMount( "computercraft", "lua/treasure" ); } @Nonnull - private static String getSubPath(@Nonnull ItemStack stack) { + private static String getSubPath( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_SUB_PATH) ? nbt.getString(NBT_SUB_PATH) : "dan200/alongtimeago"; + return nbt != null && nbt.contains( NBT_SUB_PATH ) ? nbt.getString( NBT_SUB_PATH ) : "dan200/alongtimeago"; } } diff --git a/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java b/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java index 17c76ee1b..304c3581d 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java +++ b/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java @@ -6,10 +6,7 @@ package dan200.computercraft.shared.media.items; -import javax.annotation.Nonnull; - import dan200.computercraft.api.media.IMedia; - import dan200.computercraft.fabric.mixin.MusicDiscItemAccessor; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -17,34 +14,43 @@ import net.minecraft.item.MusicDiscItem; import net.minecraft.sound.SoundEvent; import net.minecraft.text.TranslatableText; +import javax.annotation.Nonnull; + /** * An implementation of IMedia for ItemRecords. */ -public final class RecordMedia implements IMedia { +public final class RecordMedia implements IMedia +{ public static final RecordMedia INSTANCE = new RecordMedia(); - private RecordMedia() { + private RecordMedia() + { } @Override - public String getLabel(@Nonnull ItemStack stack) { - return this.getAudioTitle(stack); + public String getLabel( @Nonnull ItemStack stack ) + { + return this.getAudioTitle( stack ); } @Override - public String getAudioTitle(@Nonnull ItemStack stack) { + public String getAudioTitle( @Nonnull ItemStack stack ) + { Item item = stack.getItem(); - if (!(item instanceof MusicDiscItem)) { + if( !(item instanceof MusicDiscItem) ) + { return null; } - return new TranslatableText(item.getTranslationKey() + ".desc").getString(); + return new TranslatableText( item.getTranslationKey() + ".desc" ).getString(); } @Override - public SoundEvent getAudio(@Nonnull ItemStack stack) { + public SoundEvent getAudio( @Nonnull ItemStack stack ) + { Item item = stack.getItem(); - if (!(item instanceof MusicDiscItem)) { + if( !(item instanceof MusicDiscItem) ) + { return null; } return ((MusicDiscItemAccessor) item).getSound(); diff --git a/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java b/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java index 24006f1ee..a64bce717 100644 --- a/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java +++ b/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java @@ -6,13 +6,10 @@ package dan200.computercraft.shared.media.recipes; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.media.items.ItemDisk; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.ColourTracker; import dan200.computercraft.shared.util.ColourUtils; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -24,32 +21,44 @@ import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; import net.minecraft.world.World; -public class DiskRecipe extends SpecialCraftingRecipe { - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>(DiskRecipe::new); - private final Ingredient paper = Ingredient.ofItems(Items.PAPER); - // TODO: Ingredient.fromTag( Tags.Items.DUSTS_REDSTONE ); - private final Ingredient redstone = Ingredient.ofItems(Items.REDSTONE); +import javax.annotation.Nonnull; - public DiskRecipe(Identifier id) { - super(id); +public class DiskRecipe extends SpecialCraftingRecipe +{ + public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( DiskRecipe::new ); + private final Ingredient paper = Ingredient.ofItems( Items.PAPER ); + // TODO: Ingredient.fromTag( Tags.Items.DUSTS_REDSTONE ); + private final Ingredient redstone = Ingredient.ofItems( Items.REDSTONE ); + + public DiskRecipe( Identifier id ) + { + super( id ); } @Override - public boolean matches(@Nonnull CraftingInventory inv, @Nonnull World world) { + public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) + { boolean paperFound = false; boolean redstoneFound = false; - for (int i = 0; i < inv.size(); i++) { - ItemStack stack = inv.getStack(i); + for( int i = 0; i < inv.size(); i++ ) + { + ItemStack stack = inv.getStack( i ); - if (!stack.isEmpty()) { - if (this.paper.test(stack)) { - if (paperFound) { + if( !stack.isEmpty() ) + { + if( this.paper.test( stack ) ) + { + if( paperFound ) + { return false; } paperFound = true; - } else if (this.redstone.test(stack)) { - if (redstoneFound) { + } + else if( this.redstone.test( stack ) ) + { + if( redstoneFound ) + { return false; } redstoneFound = true; @@ -66,13 +75,16 @@ public class DiskRecipe extends SpecialCraftingRecipe { @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inv) { + public ItemStack craft( @Nonnull CraftingInventory inv ) + { ColourTracker tracker = new ColourTracker(); - for (int i = 0; i < inv.size(); i++) { - ItemStack stack = inv.getStack(i); + for( int i = 0; i < inv.size(); i++ ) + { + ItemStack stack = inv.getStack( i ); - if (stack.isEmpty()) { + if( stack.isEmpty() ) + { continue; } @@ -83,23 +95,26 @@ public class DiskRecipe extends SpecialCraftingRecipe { } } - return ItemDisk.createFromIDAndColour(-1, null, tracker.hasColour() ? tracker.getColour() : Colour.BLUE.getHex()); + return ItemDisk.createFromIDAndColour( -1, null, tracker.hasColour() ? tracker.getColour() : Colour.BLUE.getHex() ); } @Override - public boolean fits(int x, int y) { + public boolean fits( int x, int y ) + { return x >= 2 && y >= 2; } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } @Nonnull @Override - public ItemStack getOutput() { - return ItemDisk.createFromIDAndColour(-1, null, Colour.BLUE.getHex()); + public ItemStack getOutput() + { + return ItemDisk.createFromIDAndColour( -1, null, Colour.BLUE.getHex() ); } } diff --git a/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java b/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java index a94940aca..13e75e73b 100644 --- a/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java +++ b/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java @@ -6,10 +6,7 @@ package dan200.computercraft.shared.media.recipes; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.media.items.ItemPrintout; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -20,30 +17,37 @@ import net.minecraft.recipe.SpecialRecipeSerializer; import net.minecraft.util.Identifier; import net.minecraft.world.World; -public final class PrintoutRecipe extends SpecialCraftingRecipe { - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>(PrintoutRecipe::new); - private final Ingredient paper = Ingredient.ofItems(net.minecraft.item.Items.PAPER); - private final Ingredient leather = Ingredient.ofItems(net.minecraft.item.Items.LEATHER); - private final Ingredient string = Ingredient.ofItems(Items.STRING); +import javax.annotation.Nonnull; - private PrintoutRecipe(Identifier id) { - super(id); +public final class PrintoutRecipe extends SpecialCraftingRecipe +{ + public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( PrintoutRecipe::new ); + private final Ingredient paper = Ingredient.ofItems( net.minecraft.item.Items.PAPER ); + private final Ingredient leather = Ingredient.ofItems( net.minecraft.item.Items.LEATHER ); + private final Ingredient string = Ingredient.ofItems( Items.STRING ); + + private PrintoutRecipe( Identifier id ) + { + super( id ); } @Nonnull @Override - public ItemStack getOutput() { - return ItemPrintout.createMultipleFromTitleAndText(null, null, null); + public ItemStack getOutput() + { + return ItemPrintout.createMultipleFromTitleAndText( null, null, null ); } @Override - public boolean matches(@Nonnull CraftingInventory inventory, @Nonnull World world) { - return !this.craft(inventory).isEmpty(); + public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) + { + return !this.craft( inventory ).isEmpty(); } @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inventory) { + public ItemStack craft( @Nonnull CraftingInventory inventory ) + { // See if we match the recipe, and extract the input disk ID and dye colour int numPages = 0; int numPrintouts = 0; @@ -51,30 +55,44 @@ public final class PrintoutRecipe extends SpecialCraftingRecipe { boolean stringFound = false; boolean leatherFound = false; boolean printoutFound = false; - for (int y = 0; y < inventory.getHeight(); y++) { - for (int x = 0; x < inventory.getWidth(); x++) { - ItemStack stack = inventory.getStack(x + y * inventory.getWidth()); - if (!stack.isEmpty()) { - if (stack.getItem() instanceof ItemPrintout && ((ItemPrintout) stack.getItem()).getType() != ItemPrintout.Type.BOOK) { - if (printouts == null) { + for( int y = 0; y < inventory.getHeight(); y++ ) + { + for( int x = 0; x < inventory.getWidth(); x++ ) + { + ItemStack stack = inventory.getStack( x + y * inventory.getWidth() ); + if( !stack.isEmpty() ) + { + if( stack.getItem() instanceof ItemPrintout && ((ItemPrintout) stack.getItem()).getType() != ItemPrintout.Type.BOOK ) + { + if( printouts == null ) + { printouts = new ItemStack[9]; } printouts[numPrintouts] = stack; - numPages += ItemPrintout.getPageCount(stack); + numPages += ItemPrintout.getPageCount( stack ); numPrintouts++; printoutFound = true; - } else if (this.paper.test(stack)) { - if (printouts == null) { + } + else if( this.paper.test( stack ) ) + { + if( printouts == null ) + { printouts = new ItemStack[9]; } printouts[numPrintouts] = stack; numPages++; numPrintouts++; - } else if (this.string.test(stack) && !stringFound) { + } + else if( this.string.test( stack ) && !stringFound ) + { stringFound = true; - } else if (this.leather.test(stack) && !leatherFound) { + } + else if( this.leather.test( stack ) && !leatherFound ) + { leatherFound = true; - } else { + } + else + { return ItemStack.EMPTY; } } @@ -82,25 +100,32 @@ public final class PrintoutRecipe extends SpecialCraftingRecipe { } // Build some pages with what was passed in - if (numPages <= ItemPrintout.MAX_PAGES && stringFound && printoutFound && numPrintouts >= (leatherFound ? 1 : 2)) { + if( numPages <= ItemPrintout.MAX_PAGES && stringFound && printoutFound && numPrintouts >= (leatherFound ? 1 : 2) ) + { String[] text = new String[numPages * ItemPrintout.LINES_PER_PAGE]; String[] colours = new String[numPages * ItemPrintout.LINES_PER_PAGE]; int line = 0; - for (int printout = 0; printout < numPrintouts; printout++) { + for( int printout = 0; printout < numPrintouts; printout++ ) + { ItemStack stack = printouts[printout]; - if (stack.getItem() instanceof ItemPrintout) { + if( stack.getItem() instanceof ItemPrintout ) + { // Add a printout - String[] pageText = ItemPrintout.getText(printouts[printout]); - String[] pageColours = ItemPrintout.getColours(printouts[printout]); - for (int pageLine = 0; pageLine < pageText.length; pageLine++) { + String[] pageText = ItemPrintout.getText( printouts[printout] ); + String[] pageColours = ItemPrintout.getColours( printouts[printout] ); + for( int pageLine = 0; pageLine < pageText.length; pageLine++ ) + { text[line] = pageText[pageLine]; colours[line] = pageColours[pageLine]; line++; } - } else { + } + else + { // Add a blank page - for (int pageLine = 0; pageLine < ItemPrintout.LINES_PER_PAGE; pageLine++) { + for( int pageLine = 0; pageLine < ItemPrintout.LINES_PER_PAGE; pageLine++ ) + { text[line] = ""; colours[line] = ""; line++; @@ -109,14 +134,18 @@ public final class PrintoutRecipe extends SpecialCraftingRecipe { } String title = null; - if (printouts[0].getItem() instanceof ItemPrintout) { - title = ItemPrintout.getTitle(printouts[0]); + if( printouts[0].getItem() instanceof ItemPrintout ) + { + title = ItemPrintout.getTitle( printouts[0] ); } - if (leatherFound) { - return ItemPrintout.createBookFromTitleAndText(title, text, colours); - } else { - return ItemPrintout.createMultipleFromTitleAndText(title, text, colours); + if( leatherFound ) + { + return ItemPrintout.createBookFromTitleAndText( title, text, colours ); + } + else + { + return ItemPrintout.createMultipleFromTitleAndText( title, text, colours ); } } @@ -124,13 +153,15 @@ public final class PrintoutRecipe extends SpecialCraftingRecipe { } @Override - public boolean fits(int x, int y) { + public boolean fits( int x, int y ) + { return x >= 3 && y >= 3; } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } } diff --git a/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java b/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java index 40debae0b..cf99a32be 100644 --- a/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java +++ b/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java @@ -6,27 +6,20 @@ package dan200.computercraft.shared.network; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.network.client.ChatTableClientMessage; -import dan200.computercraft.shared.network.client.ComputerDataClientMessage; -import dan200.computercraft.shared.network.client.ComputerDeletedClientMessage; -import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage; -import dan200.computercraft.shared.network.client.PlayRecordClientMessage; -import dan200.computercraft.shared.network.server.ComputerActionServerMessage; -import dan200.computercraft.shared.network.server.KeyEventServerMessage; -import dan200.computercraft.shared.network.server.MouseEventServerMessage; -import dan200.computercraft.shared.network.server.QueueEventServerMessage; -import dan200.computercraft.shared.network.server.RequestComputerMessage; +import dan200.computercraft.shared.network.client.*; +import dan200.computercraft.shared.network.server.*; import io.netty.buffer.Unpooled; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; +import net.fabricmc.fabric.api.network.PacketContext; +import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; @@ -38,109 +31,119 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; -import net.fabricmc.fabric.api.network.PacketContext; -import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; -import net.fabricmc.loader.api.FabricLoader; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; -public final class NetworkHandler { +public final class NetworkHandler +{ private static final Int2ObjectMap> packetReaders = new Int2ObjectOpenHashMap<>(); private static final Object2IntMap> packetIds = new Object2IntOpenHashMap<>(); - private static final Identifier ID = new Identifier(ComputerCraft.MOD_ID, "main"); + private static final Identifier ID = new Identifier( ComputerCraft.MOD_ID, "main" ); - private NetworkHandler() { + private NetworkHandler() + { } - public static void setup() { - ServerSidePacketRegistry.INSTANCE.register(ID, NetworkHandler::receive); - if (FabricLoader.getInstance() - .getEnvironmentType() == EnvType.CLIENT) { - ClientSidePacketRegistry.INSTANCE.register(ID, NetworkHandler::receive); + public static void setup() + { + ServerSidePacketRegistry.INSTANCE.register( ID, NetworkHandler::receive ); + if( FabricLoader.getInstance() + .getEnvironmentType() == EnvType.CLIENT ) + { + ClientSidePacketRegistry.INSTANCE.register( ID, NetworkHandler::receive ); } // Server messages - registerMainThread(0, ComputerActionServerMessage::new); - registerMainThread(1, QueueEventServerMessage::new); - registerMainThread(2, RequestComputerMessage::new); - registerMainThread(3, KeyEventServerMessage::new); - registerMainThread(4, MouseEventServerMessage::new); + registerMainThread( 0, ComputerActionServerMessage::new ); + registerMainThread( 1, QueueEventServerMessage::new ); + registerMainThread( 2, RequestComputerMessage::new ); + registerMainThread( 3, KeyEventServerMessage::new ); + registerMainThread( 4, MouseEventServerMessage::new ); // Client messages - registerMainThread(10, ChatTableClientMessage::new); - registerMainThread(11, ComputerDataClientMessage::new); - registerMainThread(12, ComputerDeletedClientMessage::new); - registerMainThread(13, ComputerTerminalClientMessage::new); - registerMainThread(14, PlayRecordClientMessage.class, PlayRecordClientMessage::new); + registerMainThread( 10, ChatTableClientMessage::new ); + registerMainThread( 11, ComputerDataClientMessage::new ); + registerMainThread( 12, ComputerDeletedClientMessage::new ); + registerMainThread( 13, ComputerTerminalClientMessage::new ); + registerMainThread( 14, PlayRecordClientMessage.class, PlayRecordClientMessage::new ); } - private static void receive(PacketContext context, PacketByteBuf buffer) { + private static void receive( PacketContext context, PacketByteBuf buffer ) + { int type = buffer.readByte(); - packetReaders.get(type) - .accept(context, buffer); + packetReaders.get( type ) + .accept( context, buffer ); } /** * /** Register packet, and a thread-unsafe handler for it. * - * @param id The identifier for this packet type + * @param id The identifier for this packet type * @param factory The factory for this type of packet. */ - private static void registerMainThread(int id, Supplier factory) { - registerMainThread(id, getType(factory), buf -> { + private static void registerMainThread( int id, Supplier factory ) + { + registerMainThread( id, getType( factory ), buf -> { T instance = factory.get(); - instance.fromBytes(buf); + instance.fromBytes( buf ); return instance; - }); + } ); } /** * /** Register packet, and a thread-unsafe handler for it. * - * @param id The identifier for this packet type + * @param id The identifier for this packet type * @param decoder The factory for this type of packet. */ - private static void registerMainThread(int id, Class type, Function decoder) { - packetIds.put(type, id); - packetReaders.put(id, (context, buf) -> { - T result = decoder.apply(buf); + private static void registerMainThread( int id, Class type, Function decoder ) + { + packetIds.put( type, id ); + packetReaders.put( id, ( context, buf ) -> { + T result = decoder.apply( buf ); context.getTaskQueue() - .execute(() -> result.handle(context)); - }); + .execute( () -> result.handle( context ) ); + } ); } - @SuppressWarnings ("unchecked") - private static Class getType(Supplier supplier) { + @SuppressWarnings( "unchecked" ) + private static Class getType( Supplier supplier ) + { return (Class) supplier.get() - .getClass(); + .getClass(); } - public static void sendToPlayer(PlayerEntity player, NetworkMessage packet) { - ((ServerPlayerEntity) player).networkHandler.sendPacket(new CustomPayloadS2CPacket(ID, encode(packet))); + public static void sendToPlayer( PlayerEntity player, NetworkMessage packet ) + { + ((ServerPlayerEntity) player).networkHandler.sendPacket( new CustomPayloadS2CPacket( ID, encode( packet ) ) ); } - private static PacketByteBuf encode(NetworkMessage message) { - PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); - buf.writeByte(packetIds.getInt(message.getClass())); - message.toBytes(buf); + private static PacketByteBuf encode( NetworkMessage message ) + { + PacketByteBuf buf = new PacketByteBuf( Unpooled.buffer() ); + buf.writeByte( packetIds.getInt( message.getClass() ) ); + message.toBytes( buf ); return buf; } - public static void sendToAllPlayers(MinecraftServer server, NetworkMessage packet) { + public static void sendToAllPlayers( MinecraftServer server, NetworkMessage packet ) + { server.getPlayerManager() - .sendToAll(new CustomPayloadS2CPacket(ID, encode(packet))); + .sendToAll( new CustomPayloadS2CPacket( ID, encode( packet ) ) ); } - @Environment (EnvType.CLIENT) - public static void sendToServer(NetworkMessage packet) { - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CustomPayloadC2SPacket(ID, encode(packet))); + @Environment( EnvType.CLIENT ) + public static void sendToServer( NetworkMessage packet ) + { + MinecraftClient.getInstance().player.networkHandler.sendPacket( new CustomPayloadC2SPacket( ID, encode( packet ) ) ); } - public static void sendToAllAround(NetworkMessage packet, World world, Vec3d pos, double range) { + public static void sendToAllAround( NetworkMessage packet, World world, Vec3d pos, double range ) + { world.getServer() - .getPlayerManager() - .sendToAround(null, pos.x, pos.y, pos.z, range, world.getRegistryKey(), new CustomPayloadS2CPacket(ID, encode(packet))); + .getPlayerManager() + .sendToAround( null, pos.x, pos.y, pos.z, range, world.getRegistryKey(), new CustomPayloadS2CPacket( ID, encode( packet ) ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java b/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java index 3dd43457b..911014907 100644 --- a/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java @@ -6,16 +6,16 @@ package dan200.computercraft.shared.network; -import javax.annotation.Nonnull; - +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; /** * The base interface for any message which will be sent to the client or server. */ -public interface NetworkMessage { +public interface NetworkMessage +{ /** * Write this packet to a buffer. * @@ -23,7 +23,7 @@ public interface NetworkMessage { * * @param buf The buffer to write data to. */ - void toBytes(@Nonnull PacketByteBuf buf); + void toBytes( @Nonnull PacketByteBuf buf ); /** * Read this packet from a buffer. @@ -32,8 +32,9 @@ public interface NetworkMessage { * * @param buf The buffer to read data from. */ - default void fromBytes(@Nonnull PacketByteBuf buf) { - throw new IllegalStateException("Should have been registered using a \"from bytes\" method"); + default void fromBytes( @Nonnull PacketByteBuf buf ) + { + throw new IllegalStateException( "Should have been registered using a \"from bytes\" method" ); } /** @@ -41,5 +42,5 @@ public interface NetworkMessage { * * @param context The context with which to handle this message */ - void handle(PacketContext context); + void handle( PacketContext context ); } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java index bc367af65..38edc15d3 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java @@ -6,85 +6,100 @@ package dan200.computercraft.shared.network.client; -import javax.annotation.Nonnull; - import dan200.computercraft.client.ClientTableFormatter; import dan200.computercraft.shared.command.text.TableBuilder; import dan200.computercraft.shared.network.NetworkMessage; - -import net.minecraft.network.PacketByteBuf; -import net.minecraft.text.Text; - import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.network.PacketContext; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.text.Text; -public class ChatTableClientMessage implements NetworkMessage { +import javax.annotation.Nonnull; + +public class ChatTableClientMessage implements NetworkMessage +{ private TableBuilder table; - public ChatTableClientMessage(TableBuilder table) { - if (table.getColumns() < 0) { - throw new IllegalStateException("Cannot send an empty table"); + public ChatTableClientMessage( TableBuilder table ) + { + if( table.getColumns() < 0 ) + { + throw new IllegalStateException( "Cannot send an empty table" ); } this.table = table; } - public ChatTableClientMessage() { + public ChatTableClientMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - buf.writeVarInt(this.table.getId()); - buf.writeVarInt(this.table.getColumns()); - buf.writeBoolean(this.table.getHeaders() != null); - if (this.table.getHeaders() != null) { - for (Text header : this.table.getHeaders()) { - buf.writeText(header); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + buf.writeVarInt( this.table.getId() ); + buf.writeVarInt( this.table.getColumns() ); + buf.writeBoolean( this.table.getHeaders() != null ); + if( this.table.getHeaders() != null ) + { + for( Text header : this.table.getHeaders() ) + { + buf.writeText( header ); } } - buf.writeVarInt(this.table.getRows() - .size()); - for (Text[] row : this.table.getRows()) { - for (Text column : row) { - buf.writeText(column); + buf.writeVarInt( this.table.getRows() + .size() ); + for( Text[] row : this.table.getRows() ) + { + for( Text column : row ) + { + buf.writeText( column ); } } - buf.writeVarInt(this.table.getAdditional()); + buf.writeVarInt( this.table.getAdditional() ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { + public void fromBytes( @Nonnull PacketByteBuf buf ) + { int id = buf.readVarInt(); int columns = buf.readVarInt(); TableBuilder table; - if (buf.readBoolean()) { + if( buf.readBoolean() ) + { Text[] headers = new Text[columns]; - for (int i = 0; i < columns; i++) { + for( int i = 0; i < columns; i++ ) + { headers[i] = buf.readText(); } - table = new TableBuilder(id, headers); - } else { - table = new TableBuilder(id); + table = new TableBuilder( id, headers ); + } + else + { + table = new TableBuilder( id ); } int rows = buf.readVarInt(); - for (int i = 0; i < rows; i++) { + for( int i = 0; i < rows; i++ ) + { Text[] row = new Text[columns]; - for (int j = 0; j < columns; j++) { + for( int j = 0; j < columns; j++ ) + { row[j] = buf.readText(); } - table.row(row); + table.row( row ); } - table.setAdditional(buf.readVarInt()); + table.setAdditional( buf.readVarInt() ); this.table = table; } @Override - @Environment (EnvType.CLIENT) - public void handle(PacketContext context) { - ClientTableFormatter.INSTANCE.display(this.table); + @Environment( EnvType.CLIENT ) + public void handle( PacketContext context ) + { + ClientTableFormatter.INSTANCE.display( this.table ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerClientMessage.java index d1edec94e..7e73f4eb5 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerClientMessage.java @@ -6,45 +6,52 @@ package dan200.computercraft.shared.network.client; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.network.NetworkMessage; - import net.minecraft.network.PacketByteBuf; +import javax.annotation.Nonnull; + /** * A packet, which performs an action on a {@link ClientComputer}. */ -public abstract class ComputerClientMessage implements NetworkMessage { +public abstract class ComputerClientMessage implements NetworkMessage +{ private int instanceId; - public ComputerClientMessage(int instanceId) { + public ComputerClientMessage( int instanceId ) + { this.instanceId = instanceId; } - public ComputerClientMessage() { + public ComputerClientMessage() + { } - public int getInstanceId() { + public int getInstanceId() + { return this.instanceId; } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - buf.writeVarInt(this.instanceId); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + buf.writeVarInt( this.instanceId ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { + public void fromBytes( @Nonnull PacketByteBuf buf ) + { this.instanceId = buf.readVarInt(); } - public ClientComputer getComputer() { - ClientComputer computer = ComputerCraft.clientComputerRegistry.get(this.instanceId); - if (computer == null) { - ComputerCraft.clientComputerRegistry.add(this.instanceId, computer = new ClientComputer(this.instanceId)); + public ClientComputer getComputer() + { + ClientComputer computer = ComputerCraft.clientComputerRegistry.get( this.instanceId ); + if( computer == null ) + { + ComputerCraft.clientComputerRegistry.add( this.instanceId, computer = new ClientComputer( this.instanceId ) ); } return computer; } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java index a466bef3e..4eb829cc1 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java @@ -6,48 +6,52 @@ package dan200.computercraft.shared.network.client; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerComputer; - +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.PacketByteBuf; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; /** * Provides additional data about a client computer, such as its ID and current state. */ -public class ComputerDataClientMessage extends ComputerClientMessage { +public class ComputerDataClientMessage extends ComputerClientMessage +{ private ComputerState state; private CompoundTag userData; - public ComputerDataClientMessage(ServerComputer computer) { - super(computer.getInstanceID()); + public ComputerDataClientMessage( ServerComputer computer ) + { + super( computer.getInstanceID() ); this.state = computer.getState(); this.userData = computer.getUserData(); } - public ComputerDataClientMessage() { + public ComputerDataClientMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - super.toBytes(buf); - buf.writeEnumConstant(this.state); - buf.writeCompoundTag(this.userData); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + super.toBytes( buf ); + buf.writeEnumConstant( this.state ); + buf.writeCompoundTag( this.userData ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { - super.fromBytes(buf); - this.state = buf.readEnumConstant(ComputerState.class); + public void fromBytes( @Nonnull PacketByteBuf buf ) + { + super.fromBytes( buf ); + this.state = buf.readEnumConstant( ComputerState.class ); this.userData = buf.readCompoundTag(); } @Override - public void handle(PacketContext context) { - this.getComputer().setState(this.state, this.userData); + public void handle( PacketContext context ) + { + this.getComputer().setState( this.state, this.userData ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java index f3a3c8d22..5b858d6e2 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java @@ -7,19 +7,22 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.ComputerCraft; - import net.fabricmc.fabric.api.network.PacketContext; -public class ComputerDeletedClientMessage extends ComputerClientMessage { - public ComputerDeletedClientMessage(int instanceId) { - super(instanceId); +public class ComputerDeletedClientMessage extends ComputerClientMessage +{ + public ComputerDeletedClientMessage( int instanceId ) + { + super( instanceId ); } - public ComputerDeletedClientMessage() { + public ComputerDeletedClientMessage() + { } @Override - public void handle(PacketContext context) { - ComputerCraft.clientComputerRegistry.remove(this.getInstanceId()); + public void handle( PacketContext context ) + { + ComputerCraft.clientComputerRegistry.remove( this.getInstanceId() ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java index 8d341a368..d469c8e83 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java @@ -6,37 +6,42 @@ package dan200.computercraft.shared.network.client; -import javax.annotation.Nonnull; - +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; -public class ComputerTerminalClientMessage extends ComputerClientMessage { +public class ComputerTerminalClientMessage extends ComputerClientMessage +{ private TerminalState state; - public ComputerTerminalClientMessage(int instanceId, TerminalState state) { - super(instanceId); + public ComputerTerminalClientMessage( int instanceId, TerminalState state ) + { + super( instanceId ); this.state = state; } - public ComputerTerminalClientMessage() { + public ComputerTerminalClientMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - super.toBytes(buf); - this.state.write(buf); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + super.toBytes( buf ); + this.state.write( buf ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { - super.fromBytes(buf); - this.state = new TerminalState(buf); + public void fromBytes( @Nonnull PacketByteBuf buf ) + { + super.fromBytes( buf ); + this.state = new TerminalState( buf ); } @Override - public void handle(PacketContext context) { - this.getComputer().read(this.state); + public void handle( PacketContext context ) + { + this.getComputer().read( this.state ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java index 5266f9563..c5966d88e 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java @@ -5,51 +5,56 @@ */ package dan200.computercraft.shared.network.client; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.peripheral.monitor.TileMonitor; - +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.math.BlockPos; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; -public class MonitorClientMessage implements NetworkMessage { +public class MonitorClientMessage implements NetworkMessage +{ private final BlockPos pos; private final TerminalState state; - public MonitorClientMessage(BlockPos pos, TerminalState state) { + public MonitorClientMessage( BlockPos pos, TerminalState state ) + { this.pos = pos; this.state = state; } - public MonitorClientMessage(@Nonnull PacketByteBuf buf) { + public MonitorClientMessage( @Nonnull PacketByteBuf buf ) + { this.pos = buf.readBlockPos(); - this.state = new TerminalState(buf); + this.state = new TerminalState( buf ); } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - buf.writeBlockPos(this.pos); - this.state.write(buf); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + buf.writeBlockPos( this.pos ); + this.state.write( buf ); } @Override - public void handle(PacketContext context) { + public void handle( PacketContext context ) + { ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (player == null || player.world == null) { + if( player == null || player.world == null ) + { return; } - BlockEntity te = player.world.getBlockEntity(this.pos); - if (!(te instanceof TileMonitor)) { + BlockEntity te = player.world.getBlockEntity( this.pos ); + if( !(te instanceof TileMonitor) ) + { return; } - ((TileMonitor) te).read(this.state); + ((TileMonitor) te).read( this.state ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java index 0416c9ea5..e8c283653 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java @@ -6,11 +6,11 @@ package dan200.computercraft.shared.network.client; -import javax.annotation.Nonnull; - import dan200.computercraft.fabric.mixin.SoundEventAccess; import dan200.computercraft.shared.network.NetworkMessage; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.client.MinecraftClient; import net.minecraft.network.PacketByteBuf; import net.minecraft.sound.SoundEvent; @@ -18,9 +18,7 @@ import net.minecraft.text.LiteralText; import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; /** * Starts or stops a record on the client, depending on if {@link #soundEvent} is {@code null}. @@ -29,53 +27,66 @@ import net.fabricmc.fabric.api.network.PacketContext; * * @see dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive */ -public class PlayRecordClientMessage implements NetworkMessage { +public class PlayRecordClientMessage implements NetworkMessage +{ private final BlockPos pos; private final String name; private final SoundEvent soundEvent; - public PlayRecordClientMessage(BlockPos pos, SoundEvent event, String name) { + public PlayRecordClientMessage( BlockPos pos, SoundEvent event, String name ) + { this.pos = pos; this.name = name; this.soundEvent = event; } - public PlayRecordClientMessage(BlockPos pos) { + public PlayRecordClientMessage( BlockPos pos ) + { this.pos = pos; this.name = null; this.soundEvent = null; } - public PlayRecordClientMessage(PacketByteBuf buf) { + public PlayRecordClientMessage( PacketByteBuf buf ) + { this.pos = buf.readBlockPos(); - if (buf.readBoolean()) { - this.name = buf.readString(Short.MAX_VALUE); - this.soundEvent = Registry.SOUND_EVENT.get(buf.readIdentifier()); - } else { + if( buf.readBoolean() ) + { + this.name = buf.readString( Short.MAX_VALUE ); + this.soundEvent = Registry.SOUND_EVENT.get( buf.readIdentifier() ); + } + else + { this.name = null; this.soundEvent = null; } } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - buf.writeBlockPos(this.pos); - if (this.soundEvent == null) { - buf.writeBoolean(false); - } else { - buf.writeBoolean(true); - buf.writeString(this.name); - buf.writeIdentifier(((SoundEventAccess)this.soundEvent).getId()); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + buf.writeBlockPos( this.pos ); + if( this.soundEvent == null ) + { + buf.writeBoolean( false ); + } + else + { + buf.writeBoolean( true ); + buf.writeString( this.name ); + buf.writeIdentifier( ((SoundEventAccess) this.soundEvent).getId() ); } } @Override - @Environment (EnvType.CLIENT) - public void handle(PacketContext context) { + @Environment( EnvType.CLIENT ) + public void handle( PacketContext context ) + { MinecraftClient mc = MinecraftClient.getInstance(); - mc.worldRenderer.playSong(this.soundEvent, this.pos); - if (this.name != null) { - mc.inGameHud.setRecordPlayingOverlay(new LiteralText(this.name)); + mc.worldRenderer.playSong( this.soundEvent, this.pos ); + if( this.name != null ) + { + mc.inGameHud.setRecordPlayingOverlay( new LiteralText( this.name ) ); } } } diff --git a/src/main/java/dan200/computercraft/shared/network/client/TerminalState.java b/src/main/java/dan200/computercraft/shared/network/client/TerminalState.java index 405eb607c..425579a4f 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/TerminalState.java +++ b/src/main/java/dan200/computercraft/shared/network/client/TerminalState.java @@ -5,6 +5,15 @@ */ package dan200.computercraft.shared.network.client; +import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.util.IoUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import net.minecraft.network.PacketByteBuf; + +import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -12,24 +21,14 @@ import java.io.UncheckedIOException; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import javax.annotation.Nullable; - -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.util.IoUtil; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufInputStream; -import io.netty.buffer.ByteBufOutputStream; -import io.netty.buffer.Unpooled; - -import net.minecraft.network.PacketByteBuf; - /** * A snapshot of a terminal's state. * * This is somewhat memory inefficient (we build a buffer, only to write it elsewhere), however it means we get a complete and accurate description of a * terminal, which avoids a lot of complexities with resizing terminals, dirty states, etc... */ -public class TerminalState { +public class TerminalState +{ public final boolean colour; public final int width; @@ -37,125 +36,161 @@ public class TerminalState { private final boolean compress; - @Nullable private final ByteBuf buffer; + @Nullable + private final ByteBuf buffer; private ByteBuf compressed; - public TerminalState(boolean colour, @Nullable Terminal terminal) { - this(colour, terminal, true); + public TerminalState( boolean colour, @Nullable Terminal terminal ) + { + this( colour, terminal, true ); } - public TerminalState(boolean colour, @Nullable Terminal terminal, boolean compress) { + public TerminalState( boolean colour, @Nullable Terminal terminal, boolean compress ) + { this.colour = colour; this.compress = compress; - if (terminal == null) { + if( terminal == null ) + { this.width = this.height = 0; this.buffer = null; - } else { + } + else + { this.width = terminal.getWidth(); this.height = terminal.getHeight(); ByteBuf buf = this.buffer = Unpooled.buffer(); - terminal.write(new PacketByteBuf(buf)); + terminal.write( new PacketByteBuf( buf ) ); } } - public TerminalState(PacketByteBuf buf) { + public TerminalState( PacketByteBuf buf ) + { this.colour = buf.readBoolean(); this.compress = buf.readBoolean(); - if (buf.readBoolean()) { + if( buf.readBoolean() ) + { this.width = buf.readVarInt(); this.height = buf.readVarInt(); int length = buf.readVarInt(); - this.buffer = readCompressed(buf, length, this.compress); - } else { + this.buffer = readCompressed( buf, length, this.compress ); + } + else + { this.width = this.height = 0; this.buffer = null; } } - private static ByteBuf readCompressed(ByteBuf buf, int length, boolean compress) { - if (compress) { + private static ByteBuf readCompressed( ByteBuf buf, int length, boolean compress ) + { + if( compress ) + { ByteBuf buffer = Unpooled.buffer(); InputStream stream = null; - try { - stream = new GZIPInputStream(new ByteBufInputStream(buf, length)); + try + { + stream = new GZIPInputStream( new ByteBufInputStream( buf, length ) ); byte[] swap = new byte[8192]; - while (true) { - int bytes = stream.read(swap); - if (bytes == -1) { + while( true ) + { + int bytes = stream.read( swap ); + if( bytes == -1 ) + { break; } - buffer.writeBytes(swap, 0, bytes); + buffer.writeBytes( swap, 0, bytes ); } - } catch (IOException e) { - throw new UncheckedIOException(e); - } finally { - IoUtil.closeQuietly(stream); + } + catch( IOException e ) + { + throw new UncheckedIOException( e ); + } + finally + { + IoUtil.closeQuietly( stream ); } return buffer; - } else { - ByteBuf buffer = Unpooled.buffer(length); - buf.readBytes(buffer, length); + } + else + { + ByteBuf buffer = Unpooled.buffer( length ); + buf.readBytes( buffer, length ); return buffer; } } - public void write(PacketByteBuf buf) { - buf.writeBoolean(this.colour); - buf.writeBoolean(this.compress); + public void write( PacketByteBuf buf ) + { + buf.writeBoolean( this.colour ); + buf.writeBoolean( this.compress ); - buf.writeBoolean(this.buffer != null); - if (this.buffer != null) { - buf.writeVarInt(this.width); - buf.writeVarInt(this.height); + buf.writeBoolean( this.buffer != null ); + if( this.buffer != null ) + { + buf.writeVarInt( this.width ); + buf.writeVarInt( this.height ); ByteBuf sendBuffer = this.getCompressed(); - buf.writeVarInt(sendBuffer.readableBytes()); - buf.writeBytes(sendBuffer, sendBuffer.readerIndex(), sendBuffer.readableBytes()); + buf.writeVarInt( sendBuffer.readableBytes() ); + buf.writeBytes( sendBuffer, sendBuffer.readerIndex(), sendBuffer.readableBytes() ); } } - private ByteBuf getCompressed() { - if (this.buffer == null) { - throw new NullPointerException("buffer"); + private ByteBuf getCompressed() + { + if( this.buffer == null ) + { + throw new NullPointerException( "buffer" ); } - if (!this.compress) { + if( !this.compress ) + { return this.buffer; } - if (this.compressed != null) { + if( this.compressed != null ) + { return this.compressed; } ByteBuf compressed = Unpooled.directBuffer(); OutputStream stream = null; - try { - stream = new GZIPOutputStream(new ByteBufOutputStream(compressed)); - stream.write(this.buffer.array(), this.buffer.arrayOffset(), this.buffer.readableBytes()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } finally { - IoUtil.closeQuietly(stream); + try + { + stream = new GZIPOutputStream( new ByteBufOutputStream( compressed ) ); + stream.write( this.buffer.array(), this.buffer.arrayOffset(), this.buffer.readableBytes() ); + } + catch( IOException e ) + { + throw new UncheckedIOException( e ); + } + finally + { + IoUtil.closeQuietly( stream ); } return this.compressed = compressed; } - public boolean hasTerminal() { + public boolean hasTerminal() + { return this.buffer != null; } - public int size() { + public int size() + { return this.buffer == null ? 0 : this.buffer.readableBytes(); } - public void apply(Terminal terminal) { - if (this.buffer == null) { - throw new NullPointerException("buffer"); + public void apply( Terminal terminal ) + { + if( this.buffer == null ) + { + throw new NullPointerException( "buffer" ); } - terminal.read(new PacketByteBuf(this.buffer)); + terminal.read( new PacketByteBuf( this.buffer ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java b/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java index 7d14588f9..b19bb2c55 100644 --- a/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java +++ b/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java @@ -9,44 +9,51 @@ package dan200.computercraft.shared.network.container; import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; -public class ComputerContainerData implements ContainerData { - private static final Identifier IDENTIFIER = new Identifier(ComputerCraft.MOD_ID, "computer_container_data"); +public class ComputerContainerData implements ContainerData +{ + private static final Identifier IDENTIFIER = new Identifier( ComputerCraft.MOD_ID, "computer_container_data" ); private int id; private ComputerFamily family; - public ComputerContainerData(ServerComputer computer) { + public ComputerContainerData( ServerComputer computer ) + { this.id = computer.getInstanceID(); this.family = computer.getFamily(); } - public ComputerContainerData(PacketByteBuf byteBuf) { - this.fromBytes(byteBuf); + public ComputerContainerData( PacketByteBuf byteBuf ) + { + this.fromBytes( byteBuf ); } - public void fromBytes(PacketByteBuf buf) { + public void fromBytes( PacketByteBuf buf ) + { this.id = buf.readInt(); - this.family = buf.readEnumConstant(ComputerFamily.class); + this.family = buf.readEnumConstant( ComputerFamily.class ); } - public Identifier getId() { + public Identifier getId() + { return IDENTIFIER; } @Override - public void toBytes(PacketByteBuf buf) { - buf.writeInt(this.id); - buf.writeEnumConstant(this.family); + public void toBytes( PacketByteBuf buf ) + { + buf.writeInt( this.id ); + buf.writeEnumConstant( this.family ); } - public int getInstanceId() { + public int getInstanceId() + { return this.id; } - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.family; } } diff --git a/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java b/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java index 84d319667..10f167418 100644 --- a/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java +++ b/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java @@ -6,10 +6,7 @@ package dan200.computercraft.shared.network.container; -import java.util.function.Function; - -import javax.annotation.Nonnull; - +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.network.PacketByteBuf; @@ -18,27 +15,32 @@ import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.util.Identifier; -import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; +import javax.annotation.Nonnull; +import java.util.function.Function; /** * An extension over the basic hooks, with a more convenient way of reading and writing data. */ -public interface ContainerData { - static ScreenHandlerType toType(Identifier identifier, Function reader, - Factory factory) { - return ScreenHandlerRegistry.registerExtended(identifier, - (id, playerInventory, packetByteBuf) -> factory.create(id, - playerInventory, - reader.apply(packetByteBuf))); +public interface ContainerData +{ + static ScreenHandlerType toType( Identifier identifier, Function reader, + Factory factory ) + { + return ScreenHandlerRegistry.registerExtended( identifier, + ( id, playerInventory, packetByteBuf ) -> factory.create( id, + playerInventory, + reader.apply( packetByteBuf ) ) ); } - void toBytes(PacketByteBuf buf); + void toBytes( PacketByteBuf buf ); - default void open(PlayerEntity player, NamedScreenHandlerFactory owner) { - player.openHandledScreen(owner); + default void open( PlayerEntity player, NamedScreenHandlerFactory owner ) + { + player.openHandledScreen( owner ); } - interface Factory { - C create(int id, @Nonnull PlayerInventory inventory, T data); + interface Factory + { + C create( int id, @Nonnull PlayerInventory inventory, T data ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/container/HeldItemContainerData.java b/src/main/java/dan200/computercraft/shared/network/container/HeldItemContainerData.java index 7e75a5cd5..63ae39df6 100644 --- a/src/main/java/dan200/computercraft/shared/network/container/HeldItemContainerData.java +++ b/src/main/java/dan200/computercraft/shared/network/container/HeldItemContainerData.java @@ -6,37 +6,41 @@ package dan200.computercraft.shared.network.container; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.common.ContainerHeldItem; - import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Hand; +import javax.annotation.Nonnull; + /** * Opens a printout GUI based on the currently held item. * * @see ContainerHeldItem * @see dan200.computercraft.shared.media.items.ItemPrintout */ -public class HeldItemContainerData implements ContainerData { +public class HeldItemContainerData implements ContainerData +{ private final Hand hand; - public HeldItemContainerData(Hand hand) { + public HeldItemContainerData( Hand hand ) + { this.hand = hand; } - public HeldItemContainerData(PacketByteBuf buffer) { - this.hand = buffer.readEnumConstant(Hand.class); + public HeldItemContainerData( PacketByteBuf buffer ) + { + this.hand = buffer.readEnumConstant( Hand.class ); } @Override - public void toBytes(PacketByteBuf buf) { - buf.writeEnumConstant(this.hand); + public void toBytes( PacketByteBuf buf ) + { + buf.writeEnumConstant( this.hand ); } @Nonnull - public Hand getHand() { + public Hand getHand() + { return this.hand; } } diff --git a/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java b/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java index 963dc9b74..99ca13879 100644 --- a/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java +++ b/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java @@ -6,65 +6,75 @@ package dan200.computercraft.shared.network.container; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; +import javax.annotation.Nonnull; + /** * View an arbitrary computer on the client. * * @see dan200.computercraft.shared.command.CommandComputerCraft */ -public class ViewComputerContainerData extends ComputerContainerData { - private static final Identifier IDENTIFIER = new Identifier(ComputerCraft.MOD_ID, "view_computer_container_data"); +public class ViewComputerContainerData extends ComputerContainerData +{ + private static final Identifier IDENTIFIER = new Identifier( ComputerCraft.MOD_ID, "view_computer_container_data" ); private int width; private int height; - public ViewComputerContainerData(ServerComputer computer) { - super(computer); + public ViewComputerContainerData( ServerComputer computer ) + { + super( computer ); Terminal terminal = computer.getTerminal(); - if (terminal != null) { + if( terminal != null ) + { this.width = terminal.getWidth(); this.height = terminal.getHeight(); - } else { + } + else + { this.width = this.height = 0; } } - public ViewComputerContainerData(PacketByteBuf packetByteBuf) { - super(new PacketByteBuf(packetByteBuf.copy())); - this.fromBytes(packetByteBuf); + public ViewComputerContainerData( PacketByteBuf packetByteBuf ) + { + super( new PacketByteBuf( packetByteBuf.copy() ) ); + this.fromBytes( packetByteBuf ); } @Override - public void fromBytes(PacketByteBuf buf) { - super.fromBytes(buf); + public void fromBytes( PacketByteBuf buf ) + { + super.fromBytes( buf ); this.width = buf.readVarInt(); this.height = buf.readVarInt(); } @Override - public Identifier getId() { + public Identifier getId() + { return IDENTIFIER; } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - super.toBytes(buf); - buf.writeVarInt(this.width); - buf.writeVarInt(this.height); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + super.toBytes( buf ); + buf.writeVarInt( this.width ); + buf.writeVarInt( this.height ); } - public int getWidth() { + public int getWidth() + { return this.width; } - public int getHeight() { + public int getHeight() + { return this.height; } } diff --git a/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java index 59ea51741..8f3ac121a 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java @@ -6,52 +6,59 @@ package dan200.computercraft.shared.network.server; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.network.PacketByteBuf; -public class ComputerActionServerMessage extends ComputerServerMessage { +import javax.annotation.Nonnull; + +public class ComputerActionServerMessage extends ComputerServerMessage +{ private Action action; - public ComputerActionServerMessage(int instanceId, Action action) { - super(instanceId); + public ComputerActionServerMessage( int instanceId, Action action ) + { + super( instanceId ); this.action = action; } - public ComputerActionServerMessage() { + public ComputerActionServerMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - super.toBytes(buf); - buf.writeEnumConstant(this.action); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + super.toBytes( buf ); + buf.writeEnumConstant( this.action ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { - super.fromBytes(buf); - this.action = buf.readEnumConstant(Action.class); + public void fromBytes( @Nonnull PacketByteBuf buf ) + { + super.fromBytes( buf ); + this.action = buf.readEnumConstant( Action.class ); } @Override - protected void handle(@Nonnull ServerComputer computer, @Nonnull IContainerComputer container) { - switch (this.action) { - case TURN_ON: - computer.turnOn(); - break; - case REBOOT: - computer.reboot(); - break; - case SHUTDOWN: - computer.shutdown(); - break; + protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) + { + switch( this.action ) + { + case TURN_ON: + computer.turnOn(); + break; + case REBOOT: + computer.reboot(); + break; + case SHUTDOWN: + computer.shutdown(); + break; } } - public enum Action { + public enum Action + { TURN_ON, SHUTDOWN, REBOOT } } diff --git a/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java index 06bc1ac62..2a13e607f 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java @@ -6,56 +6,62 @@ package dan200.computercraft.shared.network.server; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.network.NetworkMessage; - +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; /** * A packet, which performs an action on a {@link ServerComputer}. * * This requires that the sending player is interacting with that computer via a {@link IContainerComputer}. */ -public abstract class ComputerServerMessage implements NetworkMessage { +public abstract class ComputerServerMessage implements NetworkMessage +{ private int instanceId; - public ComputerServerMessage(int instanceId) { + public ComputerServerMessage( int instanceId ) + { this.instanceId = instanceId; } - public ComputerServerMessage() { + public ComputerServerMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - buf.writeVarInt(this.instanceId); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + buf.writeVarInt( this.instanceId ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { + public void fromBytes( @Nonnull PacketByteBuf buf ) + { this.instanceId = buf.readVarInt(); } @Override - public void handle(PacketContext context) { - ServerComputer computer = ComputerCraft.serverComputerRegistry.get(this.instanceId); - if (computer == null) { + public void handle( PacketContext context ) + { + ServerComputer computer = ComputerCraft.serverComputerRegistry.get( this.instanceId ); + if( computer == null ) + { return; } - IContainerComputer container = computer.getContainer(context.getPlayer()); - if (container == null) { + IContainerComputer container = computer.getContainer( context.getPlayer() ); + if( container == null ) + { return; } - this.handle(computer, container); + this.handle( computer, container ); } - protected abstract void handle(@Nonnull ServerComputer computer, @Nonnull IContainerComputer container); + protected abstract void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ); } diff --git a/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java index 2edf4f2bf..5d6811d11 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/KeyEventServerMessage.java @@ -6,15 +6,15 @@ package dan200.computercraft.shared.network.server; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.InputState; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.network.PacketByteBuf; -public class KeyEventServerMessage extends ComputerServerMessage { +import javax.annotation.Nonnull; + +public class KeyEventServerMessage extends ComputerServerMessage +{ public static final int TYPE_DOWN = 0; public static final int TYPE_REPEAT = 1; public static final int TYPE_UP = 2; @@ -22,36 +22,44 @@ public class KeyEventServerMessage extends ComputerServerMessage { private int type; private int key; - public KeyEventServerMessage(int instanceId, int type, int key) { - super(instanceId); + public KeyEventServerMessage( int instanceId, int type, int key ) + { + super( instanceId ); this.type = type; this.key = key; } - public KeyEventServerMessage() { + public KeyEventServerMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - super.toBytes(buf); - buf.writeByte(this.type); - buf.writeVarInt(this.key); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + super.toBytes( buf ); + buf.writeByte( this.type ); + buf.writeVarInt( this.key ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { - super.fromBytes(buf); + public void fromBytes( @Nonnull PacketByteBuf buf ) + { + super.fromBytes( buf ); this.type = buf.readByte(); this.key = buf.readVarInt(); } @Override - protected void handle(@Nonnull ServerComputer computer, @Nonnull IContainerComputer container) { + protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) + { InputState input = container.getInput(); - if (this.type == TYPE_UP) { - input.keyUp(this.key); - } else { - input.keyDown(this.key, this.type == TYPE_REPEAT); + if( this.type == TYPE_UP ) + { + input.keyUp( this.key ); + } + else + { + input.keyDown( this.key, this.type == TYPE_REPEAT ); } } } diff --git a/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java index 9f91756f0..763e36ca1 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/MouseEventServerMessage.java @@ -6,15 +6,15 @@ package dan200.computercraft.shared.network.server; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.InputState; import dan200.computercraft.shared.computer.core.ServerComputer; - import net.minecraft.network.PacketByteBuf; -public class MouseEventServerMessage extends ComputerServerMessage { +import javax.annotation.Nonnull; + +public class MouseEventServerMessage extends ComputerServerMessage +{ public static final int TYPE_CLICK = 0; public static final int TYPE_DRAG = 1; public static final int TYPE_UP = 2; @@ -25,29 +25,33 @@ public class MouseEventServerMessage extends ComputerServerMessage { private int y; private int arg; - public MouseEventServerMessage(int instanceId, int type, int arg, int x, int y) { - super(instanceId); + public MouseEventServerMessage( int instanceId, int type, int arg, int x, int y ) + { + super( instanceId ); this.type = type; this.arg = arg; this.x = x; this.y = y; } - public MouseEventServerMessage() { + public MouseEventServerMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - super.toBytes(buf); - buf.writeByte(this.type); - buf.writeVarInt(this.arg); - buf.writeVarInt(this.x); - buf.writeVarInt(this.y); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + super.toBytes( buf ); + buf.writeByte( this.type ); + buf.writeVarInt( this.arg ); + buf.writeVarInt( this.x ); + buf.writeVarInt( this.y ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { - super.fromBytes(buf); + public void fromBytes( @Nonnull PacketByteBuf buf ) + { + super.fromBytes( buf ); this.type = buf.readByte(); this.arg = buf.readVarInt(); this.x = buf.readVarInt(); @@ -55,21 +59,23 @@ public class MouseEventServerMessage extends ComputerServerMessage { } @Override - protected void handle(@Nonnull ServerComputer computer, @Nonnull IContainerComputer container) { + protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) + { InputState input = container.getInput(); - switch (this.type) { - case TYPE_CLICK: - input.mouseClick(this.arg, this.x, this.y); - break; - case TYPE_DRAG: - input.mouseDrag(this.arg, this.x, this.y); - break; - case TYPE_UP: - input.mouseUp(this.arg, this.x, this.y); - break; - case TYPE_SCROLL: - input.mouseScroll(this.arg, this.x, this.y); - break; + switch( this.type ) + { + case TYPE_CLICK: + input.mouseClick( this.arg, this.x, this.y ); + break; + case TYPE_DRAG: + input.mouseDrag( this.arg, this.x, this.y ); + break; + case TYPE_UP: + input.mouseUp( this.arg, this.x, this.y ); + break; + case TYPE_SCROLL: + input.mouseScroll( this.arg, this.x, this.y ); + break; } } } diff --git a/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java index f6930d60a..dfa262b05 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java @@ -6,53 +6,58 @@ package dan200.computercraft.shared.network.server; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.util.NBTUtil; - import net.minecraft.nbt.CompoundTag; import net.minecraft.network.PacketByteBuf; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Queue an event on a {@link ServerComputer}. * * @see dan200.computercraft.shared.computer.core.ClientComputer#queueEvent(String) * @see ServerComputer#queueEvent(String) */ -public class QueueEventServerMessage extends ComputerServerMessage { +public class QueueEventServerMessage extends ComputerServerMessage +{ private String event; private Object[] args; - public QueueEventServerMessage(int instanceId, @Nonnull String event, @Nullable Object[] args) { - super(instanceId); + public QueueEventServerMessage( int instanceId, @Nonnull String event, @Nullable Object[] args ) + { + super( instanceId ); this.event = event; this.args = args; } - public QueueEventServerMessage() { + public QueueEventServerMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - super.toBytes(buf); - buf.writeString(this.event); - buf.writeCompoundTag(this.args == null ? null : NBTUtil.encodeObjects(this.args)); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + super.toBytes( buf ); + buf.writeString( this.event ); + buf.writeCompoundTag( this.args == null ? null : NBTUtil.encodeObjects( this.args ) ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { - super.fromBytes(buf); - this.event = buf.readString(Short.MAX_VALUE); + public void fromBytes( @Nonnull PacketByteBuf buf ) + { + super.fromBytes( buf ); + this.event = buf.readString( Short.MAX_VALUE ); CompoundTag args = buf.readCompoundTag(); - this.args = args == null ? null : NBTUtil.decodeObjects(args); + this.args = args == null ? null : NBTUtil.decodeObjects( args ); } @Override - protected void handle(@Nonnull ServerComputer computer, @Nonnull IContainerComputer container) { - computer.queueEvent(this.event, this.args); + protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) + { + computer.queueEvent( this.event, this.args ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java index f2d095cfd..0b086ad7d 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java @@ -6,41 +6,46 @@ package dan200.computercraft.shared.network.server; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.network.NetworkMessage; - +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; -public class RequestComputerMessage implements NetworkMessage { +public class RequestComputerMessage implements NetworkMessage +{ private int instance; - public RequestComputerMessage(int instance) { + public RequestComputerMessage( int instance ) + { this.instance = instance; } - public RequestComputerMessage() { + public RequestComputerMessage() + { } @Override - public void toBytes(@Nonnull PacketByteBuf buf) { - buf.writeVarInt(this.instance); + public void toBytes( @Nonnull PacketByteBuf buf ) + { + buf.writeVarInt( this.instance ); } @Override - public void fromBytes(@Nonnull PacketByteBuf buf) { + public void fromBytes( @Nonnull PacketByteBuf buf ) + { this.instance = buf.readVarInt(); } @Override - public void handle(PacketContext context) { - ServerComputer computer = ComputerCraft.serverComputerRegistry.get(this.instance); - if (computer != null) { - computer.sendComputerState(context.getPlayer()); + public void handle( PacketContext context ) + { + ServerComputer computer = ComputerCraft.serverComputerRegistry.get( this.instance ); + if( computer != null ) + { + computer.sendComputerState( context.getPlayer() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java index e5cb3c431..722f2a993 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java @@ -6,16 +6,15 @@ package dan200.computercraft.shared.peripheral.commandblock; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.computer.apis.CommandAPI; - import net.minecraft.block.entity.CommandBlockBlockEntity; import net.minecraft.util.Identifier; +import javax.annotation.Nonnull; + /** * This peripheral allows you to interact with command blocks. * @@ -25,29 +24,34 @@ import net.minecraft.util.Identifier; * * @cc.module command */ -public class CommandBlockPeripheral implements IPeripheral { - private static final Identifier CAP_ID = new Identifier(ComputerCraft.MOD_ID, "command_block"); +public class CommandBlockPeripheral implements IPeripheral +{ + private static final Identifier CAP_ID = new Identifier( ComputerCraft.MOD_ID, "command_block" ); private final CommandBlockBlockEntity commandBlock; - public CommandBlockPeripheral(CommandBlockBlockEntity commandBlock) { + public CommandBlockPeripheral( CommandBlockBlockEntity commandBlock ) + { this.commandBlock = commandBlock; } @Nonnull @Override - public String getType() { + public String getType() + { return "command"; } @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return this.commandBlock; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return other != null && other.getClass() == this.getClass(); } @@ -56,10 +60,11 @@ public class CommandBlockPeripheral implements IPeripheral { * * @return The current command. */ - @LuaFunction (mainThread = true) - public final String getCommand() { + @LuaFunction( mainThread = true ) + public final String getCommand() + { return this.commandBlock.getCommandExecutor() - .getCommand(); + .getCommand(); } /** @@ -67,12 +72,13 @@ public class CommandBlockPeripheral implements IPeripheral { * * @param command The new command. */ - @LuaFunction (mainThread = true) - public final void setCommand(String command) { + @LuaFunction( mainThread = true ) + public final void setCommand( String command ) + { this.commandBlock.getCommandExecutor() - .setCommand(command); + .setCommand( command ); this.commandBlock.getCommandExecutor() - .markDirty(); + .markDirty(); } /** @@ -82,13 +88,14 @@ public class CommandBlockPeripheral implements IPeripheral { * @cc.treturn boolean If the command completed successfully. * @cc.treturn string|nil A failure message. */ - @LuaFunction (mainThread = true) - public final Object[] runCommand() { + @LuaFunction( mainThread = true ) + public final Object[] runCommand() + { this.commandBlock.getCommandExecutor() - .execute(this.commandBlock.getWorld()); + .execute( this.commandBlock.getWorld() ); int result = this.commandBlock.getCommandExecutor() - .getSuccessCount(); - return result > 0 ? new Object[] {true} : new Object[] { + .getSuccessCount(); + return result > 0 ? new Object[] { true } : new Object[] { false, "Command failed" }; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java index c49e066bb..2eb7fd0b4 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java @@ -6,12 +6,8 @@ package dan200.computercraft.shared.peripheral.diskdrive; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -29,52 +25,66 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class BlockDiskDrive extends BlockGeneric { - static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - static final EnumProperty STATE = EnumProperty.of("state", DiskDriveState.class); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; - public BlockDiskDrive(Settings settings) { - super(settings, ComputerCraftRegistry.ModTiles.DISK_DRIVE); - this.setDefaultState(this.getStateManager().getDefaultState() - .with(FACING, Direction.NORTH) - .with(STATE, DiskDriveState.EMPTY)); +public class BlockDiskDrive extends BlockGeneric +{ + static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; + static final EnumProperty STATE = EnumProperty.of( "state", DiskDriveState.class ); + + public BlockDiskDrive( Settings settings ) + { + super( settings, ComputerCraftRegistry.ModTiles.DISK_DRIVE ); + this.setDefaultState( this.getStateManager().getDefaultState() + .with( FACING, Direction.NORTH ) + .with( STATE, DiskDriveState.EMPTY ) ); } @Nullable @Override - public BlockState getPlacementState(ItemPlacementContext placement) { - return this.getDefaultState().with(FACING, - placement.getPlayerFacing() - .getOpposite()); + public BlockState getPlacementState( ItemPlacementContext placement ) + { + return this.getDefaultState().with( FACING, + placement.getPlayerFacing() + .getOpposite() ); } @Override - public void afterBreak(@Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te - , @Nonnull ItemStack stack) { - if (te instanceof Nameable && ((Nameable) te).hasCustomName()) { - player.incrementStat(Stats.MINED.getOrCreateStat(this)); - player.addExhaustion(0.005F); + public void afterBreak( @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te + , @Nonnull ItemStack stack ) + { + if( te instanceof Nameable && ((Nameable) te).hasCustomName() ) + { + player.incrementStat( Stats.MINED.getOrCreateStat( this ) ); + player.addExhaustion( 0.005F ); - ItemStack result = new ItemStack(this); - result.setCustomName(((Nameable) te).getCustomName()); - dropStack(world, pos, result); - } else { - super.afterBreak(world, player, pos, state, te, stack); + ItemStack result = new ItemStack( this ); + result.setCustomName( ((Nameable) te).getCustomName() ); + dropStack( world, pos, result ); + } + else + { + super.afterBreak( world, player, pos, state, te, stack ); } } @Override - public void onPlaced(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, ItemStack stack) { - if (stack.hasCustomName()) { - BlockEntity tileentity = world.getBlockEntity(pos); - if (tileentity instanceof TileDiskDrive) { + public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, ItemStack stack ) + { + if( stack.hasCustomName() ) + { + BlockEntity tileentity = world.getBlockEntity( pos ); + if( tileentity instanceof TileDiskDrive ) + { ((TileDiskDrive) tileentity).customName = stack.getName(); } } } @Override - protected void appendProperties(StateManager.Builder properties) { - properties.add(FACING, STATE); + protected void appendProperties( StateManager.Builder properties ) + { + properties.add( FACING, STATE ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java index dfd7de656..41ba16eef 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java @@ -6,10 +6,7 @@ package dan200.computercraft.shared.peripheral.diskdrive; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.ComputerCraftRegistry; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -18,70 +15,90 @@ import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; -public class ContainerDiskDrive extends ScreenHandler { +import javax.annotation.Nonnull; + +public class ContainerDiskDrive extends ScreenHandler +{ private final Inventory inventory; - public ContainerDiskDrive(int id, PlayerInventory player) { - this(id, player, new SimpleInventory(1)); + public ContainerDiskDrive( int id, PlayerInventory player ) + { + this( id, player, new SimpleInventory( 1 ) ); } - public ContainerDiskDrive(int id, PlayerInventory player, Inventory inventory) { - super(ComputerCraftRegistry.ModContainers.DISK_DRIVE, id); + public ContainerDiskDrive( int id, PlayerInventory player, Inventory inventory ) + { + super( ComputerCraftRegistry.ModContainers.DISK_DRIVE, id ); this.inventory = inventory; - this.addSlot(new Slot(this.inventory, 0, 8 + 4 * 18, 35)); + this.addSlot( new Slot( this.inventory, 0, 8 + 4 * 18, 35 ) ); - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 9; x++) { - this.addSlot(new Slot(player, x + y * 9 + 9, 8 + x * 18, 84 + y * 18)); + for( int y = 0; y < 3; y++ ) + { + for( int x = 0; x < 9; x++ ) + { + this.addSlot( new Slot( player, x + y * 9 + 9, 8 + x * 18, 84 + y * 18 ) ); } } - for (int x = 0; x < 9; x++) { - this.addSlot(new Slot(player, x, 8 + x * 18, 142)); + for( int x = 0; x < 9; x++ ) + { + this.addSlot( new Slot( player, x, 8 + x * 18, 142 ) ); } } @Nonnull @Override - public ItemStack transferSlot(@Nonnull PlayerEntity player, int slotIndex) { - Slot slot = this.slots.get(slotIndex); - if (slot == null || !slot.hasStack()) { + public ItemStack transferSlot( @Nonnull PlayerEntity player, int slotIndex ) + { + Slot slot = this.slots.get( slotIndex ); + if( slot == null || !slot.hasStack() ) + { return ItemStack.EMPTY; } ItemStack existing = slot.getStack() - .copy(); + .copy(); ItemStack result = existing.copy(); - if (slotIndex == 0) { + if( slotIndex == 0 ) + { // Insert into player inventory - if (!this.insertItem(existing, 1, 37, true)) { + if( !this.insertItem( existing, 1, 37, true ) ) + { return ItemStack.EMPTY; } - } else { + } + else + { // Insert into drive inventory - if (!this.insertItem(existing, 0, 1, false)) { + if( !this.insertItem( existing, 0, 1, false ) ) + { return ItemStack.EMPTY; } } - if (existing.isEmpty()) { - slot.setStack(ItemStack.EMPTY); - } else { + if( existing.isEmpty() ) + { + slot.setStack( ItemStack.EMPTY ); + } + else + { slot.markDirty(); } - if (existing.getCount() == result.getCount()) { + if( existing.getCount() == result.getCount() ) + { return ItemStack.EMPTY; } - slot.onTakeItem(player, existing); + slot.onTakeItem( player, existing ); return result; } @Override - public boolean canUse(@Nonnull PlayerEntity player) { - return this.inventory.canPlayerUse(player); + public boolean canUse( @Nonnull PlayerEntity player ) + { + return this.inventory.canPlayerUse( player ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java index 58c4daba0..6ab85c4ae 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.peripheral.diskdrive; -import java.util.Optional; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.media.IMedia; @@ -19,9 +14,12 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.MediaProviders; import dan200.computercraft.shared.media.items.ItemDisk; import dan200.computercraft.shared.util.StringUtil; - import net.minecraft.item.ItemStack; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Optional; + /** * Disk drives are a peripheral which allow you to read and write to floppy disks and other "mountable media" (such as computers or turtles). They also * allow you to {@link #playAudio play records}. @@ -34,37 +32,44 @@ import net.minecraft.item.ItemStack; * * @cc.module drive */ -public class DiskDrivePeripheral implements IPeripheral { +public class DiskDrivePeripheral implements IPeripheral +{ private final TileDiskDrive diskDrive; - DiskDrivePeripheral(TileDiskDrive diskDrive) { + DiskDrivePeripheral( TileDiskDrive diskDrive ) + { this.diskDrive = diskDrive; } @Nonnull @Override - public String getType() { + public String getType() + { return "drive"; } @Override - public void attach(@Nonnull IComputerAccess computer) { - this.diskDrive.mount(computer); + public void attach( @Nonnull IComputerAccess computer ) + { + this.diskDrive.mount( computer ); } @Override - public void detach(@Nonnull IComputerAccess computer) { - this.diskDrive.unmount(computer); + public void detach( @Nonnull IComputerAccess computer ) + { + this.diskDrive.unmount( computer ); } @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return this.diskDrive; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return this == other || other instanceof DiskDrivePeripheral && ((DiskDrivePeripheral) other).diskDrive == this.diskDrive; } @@ -74,9 +79,10 @@ public class DiskDrivePeripheral implements IPeripheral { * @return Whether a disk is currently inserted in the drive. */ @LuaFunction - public final boolean isDiskPresent() { + public final boolean isDiskPresent() + { return !this.diskDrive.getDiskStack() - .isEmpty(); + .isEmpty(); } /** @@ -86,10 +92,11 @@ public class DiskDrivePeripheral implements IPeripheral { * @cc.treturn string The label of the disk, or {@code nil} if either no disk is inserted or the disk doesn't have a label. */ @LuaFunction - public final Object[] getDiskLabel() { + public final Object[] getDiskLabel() + { ItemStack stack = this.diskDrive.getDiskStack(); - IMedia media = MediaProviders.get(stack); - return media == null ? null : new Object[] {media.getLabel(stack)}; + IMedia media = MediaProviders.get( stack ); + return media == null ? null : new Object[] { media.getLabel( stack ) }; } /** @@ -102,19 +109,22 @@ public class DiskDrivePeripheral implements IPeripheral { * @param labelA The new label of the disk, or {@code nil} to clear. * @throws LuaException If the disk's label can't be changed. */ - @LuaFunction (mainThread = true) - public final void setDiskLabel(Optional labelA) throws LuaException { - String label = labelA.orElse(null); + @LuaFunction( mainThread = true ) + public final void setDiskLabel( Optional labelA ) throws LuaException + { + String label = labelA.orElse( null ); ItemStack stack = this.diskDrive.getDiskStack(); - IMedia media = MediaProviders.get(stack); - if (media == null) { + IMedia media = MediaProviders.get( stack ); + if( media == null ) + { return; } - if (!media.setLabel(stack, StringUtil.normaliseLabel(label))) { - throw new LuaException("Disk label cannot be changed"); + if( !media.setLabel( stack, StringUtil.normaliseLabel( label ) ) ) + { + throw new LuaException( "Disk label cannot be changed" ); } - this.diskDrive.setDiskStack(stack); + this.diskDrive.setDiskStack( stack ); } /** @@ -124,8 +134,9 @@ public class DiskDrivePeripheral implements IPeripheral { * @return Whether a disk with data is inserted. */ @LuaFunction - public final boolean hasData(IComputerAccess computer) { - return this.diskDrive.getDiskMountPath(computer) != null; + public final boolean hasData( IComputerAccess computer ) + { + return this.diskDrive.getDiskMountPath( computer ) != null; } /** @@ -136,8 +147,9 @@ public class DiskDrivePeripheral implements IPeripheral { */ @LuaFunction @Nullable - public final String getMountPath(IComputerAccess computer) { - return this.diskDrive.getDiskMountPath(computer); + public final String getMountPath( IComputerAccess computer ) + { + return this.diskDrive.getDiskMountPath( computer ); } /** @@ -146,10 +158,11 @@ public class DiskDrivePeripheral implements IPeripheral { * @return Whether a disk with audio is inserted. */ @LuaFunction - public final boolean hasAudio() { + public final boolean hasAudio() + { ItemStack stack = this.diskDrive.getDiskStack(); - IMedia media = MediaProviders.get(stack); - return media != null && media.getAudio(stack) != null; + IMedia media = MediaProviders.get( stack ); + return media != null && media.getAudio( stack ) != null; } /** @@ -160,17 +173,19 @@ public class DiskDrivePeripheral implements IPeripheral { */ @LuaFunction @Nullable - public final Object getAudioTitle() { + public final Object getAudioTitle() + { ItemStack stack = this.diskDrive.getDiskStack(); - IMedia media = MediaProviders.get(stack); - return media != null ? media.getAudioTitle(stack) : false; + IMedia media = MediaProviders.get( stack ); + return media != null ? media.getAudioTitle( stack ) : false; } /** * Plays the audio in the inserted disk, if available. */ @LuaFunction - public final void playAudio() { + public final void playAudio() + { this.diskDrive.playDiskAudio(); } @@ -180,7 +195,8 @@ public class DiskDrivePeripheral implements IPeripheral { * @see #playAudio */ @LuaFunction - public final void stopAudio() { + public final void stopAudio() + { this.diskDrive.stopDiskAudio(); } @@ -188,7 +204,8 @@ public class DiskDrivePeripheral implements IPeripheral { * Ejects any disk that may be in the drive. */ @LuaFunction - public final void ejectDisk() { + public final void ejectDisk() + { this.diskDrive.ejectDisk(); } @@ -199,8 +216,9 @@ public class DiskDrivePeripheral implements IPeripheral { * @cc.treturn number The The ID of the disk in the drive, or {@code nil} if no disk with an ID is inserted. */ @LuaFunction - public final Object[] getDiskID() { + public final Object[] getDiskID() + { ItemStack disk = this.diskDrive.getDiskStack(); - return disk.getItem() instanceof ItemDisk ? new Object[] {ItemDisk.getDiskID(disk)} : null; + return disk.getItem() instanceof ItemDisk ? new Object[] { ItemDisk.getDiskID( disk ) } : null; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveState.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveState.java index 6392aa590..56543796d 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveState.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveState.java @@ -6,22 +6,25 @@ package dan200.computercraft.shared.peripheral.diskdrive; -import javax.annotation.Nonnull; - import net.minecraft.util.StringIdentifiable; -public enum DiskDriveState implements StringIdentifiable { - EMPTY("empty"), FULL("full"), INVALID("invalid"); +import javax.annotation.Nonnull; + +public enum DiskDriveState implements StringIdentifiable +{ + EMPTY( "empty" ), FULL( "full" ), INVALID( "invalid" ); private final String name; - DiskDriveState(String name) { + DiskDriveState( String name ) + { this.name = name; } @Override @Nonnull - public String asString() { + public String asString() + { return this.name; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java index 231b34d65..23a2fc3bd 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java @@ -6,13 +6,6 @@ package dan200.computercraft.shared.peripheral.diskdrive; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.media.IMedia; @@ -24,7 +17,6 @@ import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.util.DefaultInventory; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.RecordUtil; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.ItemEntity; @@ -45,112 +37,149 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -public final class TileDiskDrive extends TileGeneric implements DefaultInventory, Tickable, IPeripheralTile, Nameable, NamedScreenHandlerFactory { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public final class TileDiskDrive extends TileGeneric implements DefaultInventory, Tickable, IPeripheralTile, Nameable, NamedScreenHandlerFactory +{ private static final String NBT_NAME = "CustomName"; private static final String NBT_ITEM = "Item"; private final Map m_computers = new HashMap<>(); Text customName; - @Nonnull private ItemStack m_diskStack = ItemStack.EMPTY; + @Nonnull + private ItemStack m_diskStack = ItemStack.EMPTY; private IMount m_diskMount = null; private boolean m_recordQueued = false; private boolean m_recordPlaying = false; private boolean m_restartRecord = false; private boolean m_ejectQueued; - public TileDiskDrive(BlockEntityType type) { - super(type); + + public TileDiskDrive( BlockEntityType type ) + { + super( type ); } @Override - public void destroy() { - this.ejectContents(true); - if (this.m_recordPlaying) { + public void destroy() + { + this.ejectContents( true ); + if( this.m_recordPlaying ) + { this.stopRecord(); } } @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - if (player.isInSneakingPose()) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + if( player.isInSneakingPose() ) + { // Try to put a disk into the drive - ItemStack disk = player.getStackInHand(hand); - if (disk.isEmpty()) { + ItemStack disk = player.getStackInHand( hand ); + if( disk.isEmpty() ) + { return ActionResult.PASS; } - if (!this.getWorld().isClient && this.getStack(0).isEmpty() && MediaProviders.get(disk) != null) { - this.setDiskStack(disk); - player.setStackInHand(hand, ItemStack.EMPTY); + if( !this.getWorld().isClient && this.getStack( 0 ).isEmpty() && MediaProviders.get( disk ) != null ) + { + this.setDiskStack( disk ); + player.setStackInHand( hand, ItemStack.EMPTY ); } return ActionResult.SUCCESS; - } else { + } + else + { // Open the GUI - if (!this.getWorld().isClient) { - player.openHandledScreen(this); + if( !this.getWorld().isClient ) + { + player.openHandledScreen( this ); } return ActionResult.SUCCESS; } } - public Direction getDirection() { - return this.getCachedState().get(BlockDiskDrive.FACING); + public Direction getDirection() + { + return this.getCachedState().get( BlockDiskDrive.FACING ); } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); - this.customName = nbt.contains(NBT_NAME) ? Text.Serializer.fromJson(nbt.getString(NBT_NAME)) : null; - if (nbt.contains(NBT_ITEM)) { - CompoundTag item = nbt.getCompound(NBT_ITEM); - this.m_diskStack = ItemStack.fromTag(item); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); + this.customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; + if( nbt.contains( NBT_ITEM ) ) + { + CompoundTag item = nbt.getCompound( NBT_ITEM ); + this.m_diskStack = ItemStack.fromTag( item ); this.m_diskMount = null; } } @Nonnull @Override - public CompoundTag toTag(@Nonnull CompoundTag nbt) { - if (this.customName != null) { - nbt.putString(NBT_NAME, Text.Serializer.toJson(this.customName)); + public CompoundTag toTag( @Nonnull CompoundTag nbt ) + { + if( this.customName != null ) + { + nbt.putString( NBT_NAME, Text.Serializer.toJson( this.customName ) ); } - if (!this.m_diskStack.isEmpty()) { + if( !this.m_diskStack.isEmpty() ) + { CompoundTag item = new CompoundTag(); - this.m_diskStack.toTag(item); - nbt.put(NBT_ITEM, item); + this.m_diskStack.toTag( item ); + nbt.put( NBT_ITEM, item ); } - return super.toTag(nbt); + return super.toTag( nbt ); } @Override - public void markDirty() { - if (!this.world.isClient) { + public void markDirty() + { + if( !this.world.isClient ) + { this.updateBlockState(); } super.markDirty(); } @Override - public void tick() { + public void tick() + { // Ejection - if (this.m_ejectQueued) { - this.ejectContents(false); + if( this.m_ejectQueued ) + { + this.ejectContents( false ); this.m_ejectQueued = false; } // Music - synchronized (this) { - if (!this.world.isClient && this.m_recordPlaying != this.m_recordQueued || this.m_restartRecord) { + synchronized( this ) + { + if( !this.world.isClient && this.m_recordPlaying != this.m_recordQueued || this.m_restartRecord ) + { this.m_restartRecord = false; - if (this.m_recordQueued) { + if( this.m_recordQueued ) + { IMedia contents = this.getDiskMedia(); - SoundEvent record = contents != null ? contents.getAudio(this.m_diskStack) : null; - if (record != null) { + SoundEvent record = contents != null ? contents.getAudio( this.m_diskStack ) : null; + if( record != null ) + { this.m_recordPlaying = true; this.playRecord(); - } else { + } + else + { this.m_recordQueued = false; } - } else { + } + else + { this.stopRecord(); this.m_recordPlaying = false; } @@ -161,42 +190,49 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory // IInventory implementation @Override - public int size() { + public int size() + { return 1; } @Override - public boolean isEmpty() { + public boolean isEmpty() + { return this.m_diskStack.isEmpty(); } @Nonnull @Override - public ItemStack getStack(int slot) { + public ItemStack getStack( int slot ) + { return this.m_diskStack; } @Nonnull @Override - public ItemStack removeStack(int slot, int count) { - if (this.m_diskStack.isEmpty()) { + public ItemStack removeStack( int slot, int count ) + { + if( this.m_diskStack.isEmpty() ) + { return ItemStack.EMPTY; } - if (this.m_diskStack.getCount() <= count) { + if( this.m_diskStack.getCount() <= count ) + { ItemStack disk = this.m_diskStack; - this.setStack(slot, ItemStack.EMPTY); + this.setStack( slot, ItemStack.EMPTY ); return disk; } - ItemStack part = this.m_diskStack.split(count); - this.setStack(slot, this.m_diskStack.isEmpty() ? ItemStack.EMPTY : this.m_diskStack); + ItemStack part = this.m_diskStack.split( count ); + this.setStack( slot, this.m_diskStack.isEmpty() ? ItemStack.EMPTY : this.m_diskStack ); return part; } @Nonnull @Override - public ItemStack removeStack(int slot) { + public ItemStack removeStack( int slot ) + { ItemStack result = this.m_diskStack; this.m_diskStack = ItemStack.EMPTY; this.m_diskMount = null; @@ -205,31 +241,38 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory } @Override - public void setStack(int slot, @Nonnull ItemStack stack) { - if (this.getWorld().isClient) { + public void setStack( int slot, @Nonnull ItemStack stack ) + { + if( this.getWorld().isClient ) + { this.m_diskStack = stack; this.m_diskMount = null; this.markDirty(); return; } - synchronized (this) { - if (InventoryUtil.areItemsStackable(stack, this.m_diskStack)) { + synchronized( this ) + { + if( InventoryUtil.areItemsStackable( stack, this.m_diskStack ) ) + { this.m_diskStack = stack; return; } // Unmount old disk - if (!this.m_diskStack.isEmpty()) { + if( !this.m_diskStack.isEmpty() ) + { // TODO: Is this iteration thread safe? Set computers = this.m_computers.keySet(); - for (IComputerAccess computer : computers) { - this.unmountDisk(computer); + for( IComputerAccess computer : computers ) + { + this.unmountDisk( computer ); } } // Stop music - if (this.m_recordPlaying) { + if( this.m_recordPlaying ) + { this.stopRecord(); this.m_recordPlaying = false; this.m_recordQueued = false; @@ -241,121 +284,155 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory this.markDirty(); // Mount new disk - if (!this.m_diskStack.isEmpty()) { + if( !this.m_diskStack.isEmpty() ) + { Set computers = this.m_computers.keySet(); - for (IComputerAccess computer : computers) { - this.mountDisk(computer); + for( IComputerAccess computer : computers ) + { + this.mountDisk( computer ); } } } } @Override - public boolean canPlayerUse(@Nonnull PlayerEntity player) { - return this.isUsable(player, false); + public boolean canPlayerUse( @Nonnull PlayerEntity player ) + { + return this.isUsable( player, false ); } @Override - public void clear() { - this.setStack(0, ItemStack.EMPTY); + public void clear() + { + this.setStack( 0, ItemStack.EMPTY ); } @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { - return new DiskDrivePeripheral(this); + public IPeripheral getPeripheral( Direction side ) + { + return new DiskDrivePeripheral( this ); } - String getDiskMountPath(IComputerAccess computer) { - synchronized (this) { - MountInfo info = this.m_computers.get(computer); + String getDiskMountPath( IComputerAccess computer ) + { + synchronized( this ) + { + MountInfo info = this.m_computers.get( computer ); return info != null ? info.mountPath : null; } } - void mount(IComputerAccess computer) { - synchronized (this) { - this.m_computers.put(computer, new MountInfo()); - this.mountDisk(computer); + void mount( IComputerAccess computer ) + { + synchronized( this ) + { + this.m_computers.put( computer, new MountInfo() ); + this.mountDisk( computer ); } } - private synchronized void mountDisk(IComputerAccess computer) { - if (!this.m_diskStack.isEmpty()) { - MountInfo info = this.m_computers.get(computer); + private synchronized void mountDisk( IComputerAccess computer ) + { + if( !this.m_diskStack.isEmpty() ) + { + MountInfo info = this.m_computers.get( computer ); IMedia contents = this.getDiskMedia(); - if (contents != null) { - if (this.m_diskMount == null) { - this.m_diskMount = contents.createDataMount(this.m_diskStack, this.getWorld()); + if( contents != null ) + { + if( this.m_diskMount == null ) + { + this.m_diskMount = contents.createDataMount( this.m_diskStack, this.getWorld() ); } - if (this.m_diskMount != null) { - if (this.m_diskMount instanceof IWritableMount) { + if( this.m_diskMount != null ) + { + if( this.m_diskMount instanceof IWritableMount ) + { // Try mounting at the lowest numbered "disk" name we can int n = 1; - while (info.mountPath == null) { - info.mountPath = computer.mountWritable(n == 1 ? "disk" : "disk" + n, (IWritableMount) this.m_diskMount); - n++; - } - } else { - // Try mounting at the lowest numbered "disk" name we can - int n = 1; - while (info.mountPath == null) { - info.mountPath = computer.mount(n == 1 ? "disk" : "disk" + n, this.m_diskMount); + while( info.mountPath == null ) + { + info.mountPath = computer.mountWritable( n == 1 ? "disk" : "disk" + n, (IWritableMount) this.m_diskMount ); n++; } } - } else { + else + { + // Try mounting at the lowest numbered "disk" name we can + int n = 1; + while( info.mountPath == null ) + { + info.mountPath = computer.mount( n == 1 ? "disk" : "disk" + n, this.m_diskMount ); + n++; + } + } + } + else + { info.mountPath = null; } } - computer.queueEvent("disk", computer.getAttachmentName()); + computer.queueEvent( "disk", computer.getAttachmentName() ); } } - private IMedia getDiskMedia() { - return MediaProviders.get(this.getDiskStack()); + private IMedia getDiskMedia() + { + return MediaProviders.get( this.getDiskStack() ); } @Nonnull - ItemStack getDiskStack() { - return this.getStack(0); + ItemStack getDiskStack() + { + return this.getStack( 0 ); } - void setDiskStack(@Nonnull ItemStack stack) { - this.setStack(0, stack); + void setDiskStack( @Nonnull ItemStack stack ) + { + this.setStack( 0, stack ); } - void unmount(IComputerAccess computer) { - synchronized (this) { - this.unmountDisk(computer); - this.m_computers.remove(computer); + void unmount( IComputerAccess computer ) + { + synchronized( this ) + { + this.unmountDisk( computer ); + this.m_computers.remove( computer ); } } - private synchronized void unmountDisk(IComputerAccess computer) { - if (!this.m_diskStack.isEmpty()) { - MountInfo info = this.m_computers.get(computer); + private synchronized void unmountDisk( IComputerAccess computer ) + { + if( !this.m_diskStack.isEmpty() ) + { + MountInfo info = this.m_computers.get( computer ); assert info != null; - if (info.mountPath != null) { - computer.unmount(info.mountPath); + if( info.mountPath != null ) + { + computer.unmount( info.mountPath ); info.mountPath = null; } - computer.queueEvent("disk_eject", computer.getAttachmentName()); + computer.queueEvent( "disk_eject", computer.getAttachmentName() ); } } - void playDiskAudio() { - synchronized (this) { + void playDiskAudio() + { + synchronized( this ) + { IMedia media = this.getDiskMedia(); - if (media != null && media.getAudioTitle(this.m_diskStack) != null) { + if( media != null && media.getAudioTitle( this.m_diskStack ) != null ) + { this.m_recordQueued = true; this.m_restartRecord = this.m_recordPlaying; } } } - void stopDiskAudio() { - synchronized (this) { + void stopDiskAudio() + { + synchronized( this ) + { this.m_recordQueued = false; this.m_restartRecord = false; } @@ -363,47 +440,59 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory // private methods - void ejectDisk() { - synchronized (this) { + void ejectDisk() + { + synchronized( this ) + { this.m_ejectQueued = true; } } - private void updateBlockState() { - if (this.removed) { + private void updateBlockState() + { + if( this.removed ) + { return; } - if (!this.m_diskStack.isEmpty()) { + if( !this.m_diskStack.isEmpty() ) + { IMedia contents = this.getDiskMedia(); - this.updateBlockState(contents != null ? DiskDriveState.FULL : DiskDriveState.INVALID); - } else { - this.updateBlockState(DiskDriveState.EMPTY); + this.updateBlockState( contents != null ? DiskDriveState.FULL : DiskDriveState.INVALID ); + } + else + { + this.updateBlockState( DiskDriveState.EMPTY ); } } - private void updateBlockState(DiskDriveState state) { + private void updateBlockState( DiskDriveState state ) + { BlockState blockState = this.getCachedState(); - if (blockState.get(BlockDiskDrive.STATE) == state) { + if( blockState.get( BlockDiskDrive.STATE ) == state ) + { return; } - this.getWorld().setBlockState(this.getPos(), blockState.with(BlockDiskDrive.STATE, state)); + this.getWorld().setBlockState( this.getPos(), blockState.with( BlockDiskDrive.STATE, state ) ); } - private synchronized void ejectContents(boolean destroyed) { - if (this.getWorld().isClient || this.m_diskStack.isEmpty()) { + private synchronized void ejectContents( boolean destroyed ) + { + if( this.getWorld().isClient || this.m_diskStack.isEmpty() ) + { return; } // Remove the disks from the inventory ItemStack disks = this.m_diskStack; - this.setDiskStack(ItemStack.EMPTY); + this.setDiskStack( ItemStack.EMPTY ); // Spawn the item in the world int xOff = 0; int zOff = 0; - if (!destroyed) { + if( !destroyed ) + { Direction dir = this.getDirection(); xOff = dir.getOffsetX(); zOff = dir.getOffsetZ(); @@ -413,62 +502,74 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory double x = pos.getX() + 0.5 + xOff * 0.5; double y = pos.getY() + 0.75; double z = pos.getZ() + 0.5 + zOff * 0.5; - ItemEntity entityitem = new ItemEntity(this.getWorld(), x, y, z, disks); - entityitem.setVelocity(xOff * 0.15, 0, zOff * 0.15); + ItemEntity entityitem = new ItemEntity( this.getWorld(), x, y, z, disks ); + entityitem.setVelocity( xOff * 0.15, 0, zOff * 0.15 ); - this.getWorld().spawnEntity(entityitem); - if (!destroyed) { - this.getWorld().syncGlobalEvent(1000, this.getPos(), 0); + this.getWorld().spawnEntity( entityitem ); + if( !destroyed ) + { + this.getWorld().syncGlobalEvent( 1000, this.getPos(), 0 ); } } - private void playRecord() { + private void playRecord() + { IMedia contents = this.getDiskMedia(); - SoundEvent record = contents != null ? contents.getAudio(this.m_diskStack) : null; - if (record != null) { - RecordUtil.playRecord(record, contents.getAudioTitle(this.m_diskStack), this.getWorld(), this.getPos()); - } else { - RecordUtil.playRecord(null, null, this.getWorld(), this.getPos()); + SoundEvent record = contents != null ? contents.getAudio( this.m_diskStack ) : null; + if( record != null ) + { + RecordUtil.playRecord( record, contents.getAudioTitle( this.m_diskStack ), this.getWorld(), this.getPos() ); + } + else + { + RecordUtil.playRecord( null, null, this.getWorld(), this.getPos() ); } } // Private methods - private void stopRecord() { - RecordUtil.playRecord(null, null, this.getWorld(), this.getPos()); + private void stopRecord() + { + RecordUtil.playRecord( null, null, this.getWorld(), this.getPos() ); } @Nonnull @Override - public Text getName() { - return this.customName != null ? this.customName : new TranslatableText(this.getCachedState().getBlock() - .getTranslationKey()); + public Text getName() + { + return this.customName != null ? this.customName : new TranslatableText( this.getCachedState().getBlock() + .getTranslationKey() ); } @Override - public boolean hasCustomName() { + public boolean hasCustomName() + { return this.customName != null; } @Nonnull @Override - public Text getDisplayName() { + public Text getDisplayName() + { return Nameable.super.getDisplayName(); } @Nullable @Override - public Text getCustomName() { + public Text getCustomName() + { return this.customName; } @Nonnull @Override - public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) { - return new ContainerDiskDrive(id, inventory, this); + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) + { + return new ContainerDiskDrive( id, inventory, this ); } - private static class MountInfo { + private static class MountInfo + { String mountPath; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java index 15ae9320d..c4c59ee4a 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java @@ -5,22 +5,20 @@ */ package dan200.computercraft.shared.peripheral.generic; -import dan200.computercraft.api.lua.*; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IDynamicPeripheral; import dan200.computercraft.api.peripheral.IPeripheral; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.block.entity.LockableContainerBlockEntity; -import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import net.minecraft.util.Nameable; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; -import java.util.Objects; -import java.util.concurrent.locks.Lock; class GenericPeripheral implements IDynamicPeripheral { @@ -30,7 +28,7 @@ class GenericPeripheral implements IDynamicPeripheral GenericPeripheral( BlockEntity tile, List methods ) { - Identifier type = BlockEntityType.getId(tile.getType()); + Identifier type = BlockEntityType.getId( tile.getType() ); this.tile = tile; this.type = type == null ? "unknown" : type.toString(); this.methods = methods; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java index 2d7038b29..4b9a9e0ed 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java @@ -18,14 +18,15 @@ public class BlockData @Nonnull public static > T fill( @Nonnull T data, @Nonnull BlockState state ) { - data.put("name", DataHelpers.getId( state.getBlock() ) ); + data.put( "name", DataHelpers.getId( state.getBlock() ) ); Map stateTable = new HashMap<>(); - for (ImmutableMap.Entry, ? extends Comparable> entry : state.getEntries().entrySet()) { + for( ImmutableMap.Entry, ? extends Comparable> entry : state.getEntries().entrySet() ) + { Property property = entry.getKey(); - stateTable.put(property.getName(), getPropertyValue(property, entry.getValue())); + stateTable.put( property.getName(), getPropertyValue( property, entry.getValue() ) ); } - data.put("state", stateTable); + data.put( "state", stateTable ); return data; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java index 3d69d2849..210aa5b5a 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java @@ -5,7 +5,6 @@ */ package dan200.computercraft.shared.peripheral.generic.data; -import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.enchantment.Enchantment; import net.minecraft.item.Item; @@ -34,21 +33,21 @@ public final class DataHelpers @Nullable public static String getId( @Nonnull Block block ) { - Identifier id = Registry.BLOCK.getId(block); + Identifier id = Registry.BLOCK.getId( block ); return id == null ? null : id.toString(); } @Nullable public static String getId( @Nonnull Item item ) { - Identifier id = Registry.ITEM.getId(item); + Identifier id = Registry.ITEM.getId( item ); return id == null ? null : id.toString(); } @Nullable - public static String getId( @Nonnull Enchantment enchantment) + public static String getId( @Nonnull Enchantment enchantment ) { - Identifier id = Registry.ENCHANTMENT.getId(enchantment); + Identifier id = Registry.ENCHANTMENT.getId( enchantment ); return id == null ? null : id.toString(); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java index b88570bb9..bf002abac 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java @@ -7,24 +7,22 @@ package dan200.computercraft.shared.peripheral.generic.data; import com.google.gson.JsonParseException; import dan200.computercraft.shared.util.NBTUtil; -import net.fabricmc.fabric.api.tag.TagRegistry; -import net.fabricmc.fabric.impl.tag.extension.TagDelegate; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.item.EnchantedBookItem; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.tag.ServerTagManagerHolder; import net.minecraft.tag.Tag; import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Data providers for items. @@ -68,7 +66,7 @@ public class ItemData if( stack.isDamaged() ) { - data.put( "durability", 1.0 - ( stack.getDamage() / stack.getMaxDamage() ) ); + data.put( "durability", 1.0 - (stack.getDamage() / stack.getMaxDamage()) ); } /* @@ -87,7 +85,7 @@ public class ItemData data.put( "unbreakable", true ); } - data.put("tags", DataHelpers.getTags( ServerTagManagerHolder.getTagManager().getItems().getTagsFor(stack.getItem()) )); // chaos + data.put( "tags", DataHelpers.getTags( ServerTagManagerHolder.getTagManager().getItems().getTagsFor( stack.getItem() ) ) ); // chaos return data; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java index 86267a3ba..421f75492 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java @@ -51,7 +51,7 @@ public class InventoryMethods implements GenericSource @LuaFunction( mainThread = true ) public static int size( Inventory inventory ) { - return extractHandler(inventory).size(); + return extractHandler( inventory ).size(); } /** @@ -63,8 +63,9 @@ public class InventoryMethods implements GenericSource @LuaFunction( mainThread = true ) public static String name( Inventory inventory ) { - if ( inventory instanceof Nameable ) { - Nameable i = (Nameable)inventory; + if( inventory instanceof Nameable ) + { + Nameable i = (Nameable) inventory; return i.hasCustomName() ? i.getName().asString() : null; } return null; @@ -96,7 +97,7 @@ public class InventoryMethods implements GenericSource @LuaFunction( mainThread = true ) public static Map> list( Inventory inventory ) { - ItemStorage itemStorage = extractHandler(inventory); + ItemStorage itemStorage = extractHandler( inventory ); Map> result = new HashMap<>(); int size = itemStorage.size(); @@ -143,7 +144,7 @@ public class InventoryMethods implements GenericSource @LuaFunction( mainThread = true ) public static Map getItemDetail( Inventory inventory, int slot ) throws LuaException { - ItemStorage itemStorage = extractHandler(inventory); + ItemStorage itemStorage = extractHandler( inventory ); assertBetween( slot, 1, itemStorage.size(), "Slot out of range (%s)" ); @@ -281,10 +282,12 @@ public class InventoryMethods implements GenericSource @Nullable private static ItemStorage extractHandler( @Nullable Object object ) { - if ( object instanceof BlockEntity ) { - Inventory inventory = InventoryUtil.getInventory((BlockEntity) object); - if ( inventory != null ) { - return ItemStorage.wrap(inventory); + if( object instanceof BlockEntity ) + { + Inventory inventory = InventoryUtil.getInventory( (BlockEntity) object ); + if( inventory != null ) + { + return ItemStorage.wrap( inventory ); } } @@ -304,31 +307,37 @@ public class InventoryMethods implements GenericSource private static int moveItem( ItemStorage from, int fromSlot, ItemStorage to, int toSlot, final int limit ) { // Moving nothing is easy - if (limit == 0) { + if( limit == 0 ) + { return 0; } // Get stack to move - ItemStack stack = InventoryUtil.takeItems(limit, from, fromSlot, 1, fromSlot); - if (stack.isEmpty()) { + ItemStack stack = InventoryUtil.takeItems( limit, from, fromSlot, 1, fromSlot ); + if( stack.isEmpty() ) + { return 0; } int stackCount = stack.getCount(); // Move items in ItemStack remainder; - if (toSlot < 0) { - remainder = InventoryUtil.storeItems(stack, to); - } else { - remainder = InventoryUtil.storeItems(stack, to, toSlot, 1, toSlot); + if( toSlot < 0 ) + { + remainder = InventoryUtil.storeItems( stack, to ); + } + else + { + remainder = InventoryUtil.storeItems( stack, to, toSlot, 1, toSlot ); } // Calculate items moved int count = stackCount - remainder.getCount(); - if (!remainder.isEmpty()) { + if( !remainder.isEmpty() ) + { // Put the remainder back - InventoryUtil.storeItems(remainder, from, fromSlot, 1, fromSlot); + InventoryUtil.storeItems( remainder, from, fromSlot, 1, fromSlot ); } return count; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java index d87094f37..c73c966ae 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.peripheral.modem; -import java.util.HashSet; -import java.util.Set; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.network.IPacketNetwork; @@ -19,109 +14,134 @@ import dan200.computercraft.api.network.IPacketSender; import dan200.computercraft.api.network.Packet; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; - import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import javax.annotation.Nonnull; +import java.util.HashSet; +import java.util.Set; + /** * The modem peripheral allows you to send messages between computers. * * @cc.module modem */ -public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver { - private final Set m_computers = new HashSet<>(1); +public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver +{ + private final Set m_computers = new HashSet<>( 1 ); private final ModemState m_state; private IPacketNetwork m_network; - protected ModemPeripheral(ModemState state) { + protected ModemPeripheral( ModemState state ) + { this.m_state = state; } - public ModemState getModemState() { + public ModemState getModemState() + { return this.m_state; } - public void destroy() { - this.setNetwork(null); + public void destroy() + { + this.setNetwork( null ); } @Override - public void receiveSameDimension(@Nonnull Packet packet, double distance) { - if (packet.getSender() == this || !this.m_state.isOpen(packet.getChannel())) { + public void receiveSameDimension( @Nonnull Packet packet, double distance ) + { + if( packet.getSender() == this || !this.m_state.isOpen( packet.getChannel() ) ) + { return; } - synchronized (this.m_computers) { - for (IComputerAccess computer : this.m_computers) { - computer.queueEvent("modem_message", - computer.getAttachmentName(), - packet.getChannel(), - packet.getReplyChannel(), - packet.getPayload(), - distance); + synchronized( this.m_computers ) + { + for( IComputerAccess computer : this.m_computers ) + { + computer.queueEvent( "modem_message", + computer.getAttachmentName(), + packet.getChannel(), + packet.getReplyChannel(), + packet.getPayload(), + distance ); } } } @Override - public void receiveDifferentDimension(@Nonnull Packet packet) { - if (packet.getSender() == this || !this.m_state.isOpen(packet.getChannel())) { + public void receiveDifferentDimension( @Nonnull Packet packet ) + { + if( packet.getSender() == this || !this.m_state.isOpen( packet.getChannel() ) ) + { return; } - synchronized (this.m_computers) { - for (IComputerAccess computer : this.m_computers) { - computer.queueEvent("modem_message", computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload()); + synchronized( this.m_computers ) + { + for( IComputerAccess computer : this.m_computers ) + { + computer.queueEvent( "modem_message", computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload() ); } } } @Nonnull @Override - public String getType() { + public String getType() + { return "modem"; } @Override - public synchronized void attach(@Nonnull IComputerAccess computer) { - synchronized (this.m_computers) { - this.m_computers.add(computer); + public synchronized void attach( @Nonnull IComputerAccess computer ) + { + synchronized( this.m_computers ) + { + this.m_computers.add( computer ); } - this.setNetwork(this.getNetwork()); + this.setNetwork( this.getNetwork() ); } protected abstract IPacketNetwork getNetwork(); - private synchronized void setNetwork(IPacketNetwork network) { - if (this.m_network == network) { + private synchronized void setNetwork( IPacketNetwork network ) + { + if( this.m_network == network ) + { return; } // Leave old network - if (this.m_network != null) { - this.m_network.removeReceiver(this); + if( this.m_network != null ) + { + this.m_network.removeReceiver( this ); } // Set new network this.m_network = network; // Join new network - if (this.m_network != null) { - this.m_network.addReceiver(this); + if( this.m_network != null ) + { + this.m_network.addReceiver( this ); } } @Override - public synchronized void detach(@Nonnull IComputerAccess computer) { + public synchronized void detach( @Nonnull IComputerAccess computer ) + { boolean empty; - synchronized (this.m_computers) { - this.m_computers.remove(computer); + synchronized( this.m_computers ) + { + this.m_computers.remove( computer ); empty = this.m_computers.isEmpty(); } - if (empty) { - this.setNetwork(null); + if( empty ) + { + this.setNetwork( null ); } } @@ -133,13 +153,16 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa * @throws LuaException If there are too many open channels. */ @LuaFunction - public final void open(int channel) throws LuaException { - this.m_state.open(parseChannel(channel)); + public final void open( int channel ) throws LuaException + { + this.m_state.open( parseChannel( channel ) ); } - private static int parseChannel(int channel) throws LuaException { - if (channel < 0 || channel > 65535) { - throw new LuaException("Expected number in range 0-65535"); + private static int parseChannel( int channel ) throws LuaException + { + if( channel < 0 || channel > 65535 ) + { + throw new LuaException( "Expected number in range 0-65535" ); } return channel; } @@ -152,8 +175,9 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa * @throws LuaException If the channel is out of range. */ @LuaFunction - public final boolean isOpen(int channel) throws LuaException { - return this.m_state.isOpen(parseChannel(channel)); + public final boolean isOpen( int channel ) throws LuaException + { + return this.m_state.isOpen( parseChannel( channel ) ); } /** @@ -163,15 +187,17 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa * @throws LuaException If the channel is out of range. */ @LuaFunction - public final void close(int channel) throws LuaException { - this.m_state.close(parseChannel(channel)); + public final void close( int channel ) throws LuaException + { + this.m_state.close( parseChannel( channel ) ); } /** * Close all open channels. */ @LuaFunction - public final void closeAll() { + public final void closeAll() + { this.m_state.closeAll(); } @@ -180,29 +206,34 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa * *
    Note: The channel does not need be open to send a message.
    * - * @param channel The channel to send messages on. + * @param channel The channel to send messages on. * @param replyChannel The channel that responses to this message should be sent on. - * @param payload The object to send. This can be a string, number, or table. + * @param payload The object to send. This can be a string, number, or table. * @throws LuaException If the channel is out of range. */ @LuaFunction - public final void transmit(int channel, int replyChannel, Object payload) throws LuaException { - parseChannel(channel); - parseChannel(replyChannel); + public final void transmit( int channel, int replyChannel, Object payload ) throws LuaException + { + parseChannel( channel ); + parseChannel( replyChannel ); World world = this.getWorld(); Vec3d position = this.getPosition(); IPacketNetwork network = this.m_network; - if (world == null || position == null || network == null) { + if( world == null || position == null || network == null ) + { return; } - Packet packet = new Packet(channel, replyChannel, payload, this); - if (this.isInterdimensional()) { - network.transmitInterdimensional(packet); - } else { - network.transmitSameDimension(packet, this.getRange()); + Packet packet = new Packet( channel, replyChannel, payload, this ); + if( this.isInterdimensional() ) + { + network.transmitInterdimensional( packet ); + } + else + { + network.transmitSameDimension( packet, this.getRange() ); } } @@ -214,20 +245,26 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa * @return {@code true} if this is a wireless modem. */ @LuaFunction - public final boolean isWireless() { + public final boolean isWireless() + { IPacketNetwork network = this.m_network; return network != null && network.isWireless(); } @Nonnull @Override - public String getSenderID() { - synchronized (this.m_computers) { - if (this.m_computers.size() != 1) { + public String getSenderID() + { + synchronized( this.m_computers ) + { + if( this.m_computers.size() != 1 ) + { return "unknown"; - } else { + } + else + { IComputerAccess computer = this.m_computers.iterator() - .next(); + .next(); return computer.getID() + "_" + computer.getAttachmentName(); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemShapes.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemShapes.java index 548b010b9..1cf37fe63 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemShapes.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemShapes.java @@ -6,30 +6,32 @@ package dan200.computercraft.shared.peripheral.modem; -import javax.annotation.Nonnull; - import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; -public final class ModemShapes { +import javax.annotation.Nonnull; + +public final class ModemShapes +{ private static final VoxelShape[] BOXES = new VoxelShape[] { - VoxelShapes.cuboid(0.125, 0.0, 0.125, 0.875, 0.1875, 0.875), + VoxelShapes.cuboid( 0.125, 0.0, 0.125, 0.875, 0.1875, 0.875 ), // Down - VoxelShapes.cuboid(0.125, 0.8125, 0.125, 0.875, 1.0, 0.875), + VoxelShapes.cuboid( 0.125, 0.8125, 0.125, 0.875, 1.0, 0.875 ), // Up - VoxelShapes.cuboid(0.125, 0.125, 0.0, 0.875, 0.875, 0.1875), + VoxelShapes.cuboid( 0.125, 0.125, 0.0, 0.875, 0.875, 0.1875 ), // North - VoxelShapes.cuboid(0.125, 0.125, 0.8125, 0.875, 0.875, 1.0), + VoxelShapes.cuboid( 0.125, 0.125, 0.8125, 0.875, 0.875, 1.0 ), // South - VoxelShapes.cuboid(0.0, 0.125, 0.125, 0.1875, 0.875, 0.875), + VoxelShapes.cuboid( 0.0, 0.125, 0.125, 0.1875, 0.875, 0.875 ), // West - VoxelShapes.cuboid(0.8125, 0.125, 0.125, 1.0, 0.875, 0.875), + VoxelShapes.cuboid( 0.8125, 0.125, 0.125, 1.0, 0.875, 0.875 ), // East }; @Nonnull - public static VoxelShape getBounds(Direction facing) { + public static VoxelShape getBounds( Direction facing ) + { int direction = facing.ordinal(); return direction < BOXES.length ? BOXES[direction] : VoxelShapes.fullCube(); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemState.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemState.java index 883498f27..5d56ef3ae 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemState.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemState.java @@ -6,75 +6,94 @@ package dan200.computercraft.shared.peripheral.modem; -import java.util.concurrent.atomic.AtomicBoolean; - import dan200.computercraft.api.lua.LuaException; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; -public class ModemState { +import java.util.concurrent.atomic.AtomicBoolean; + +public class ModemState +{ private final Runnable onChanged; - private final AtomicBoolean changed = new AtomicBoolean(true); + private final AtomicBoolean changed = new AtomicBoolean( true ); private final IntSet channels = new IntOpenHashSet(); private boolean open = false; - public ModemState() { + public ModemState() + { this.onChanged = null; } - public ModemState(Runnable onChanged) { + public ModemState( Runnable onChanged ) + { this.onChanged = onChanged; } - public boolean pollChanged() { - return this.changed.getAndSet(false); + public boolean pollChanged() + { + return this.changed.getAndSet( false ); } - public boolean isOpen() { + public boolean isOpen() + { return this.open; } - private void setOpen(boolean open) { - if (this.open == open) { + private void setOpen( boolean open ) + { + if( this.open == open ) + { return; } this.open = open; - if (!this.changed.getAndSet(true) && this.onChanged != null) { + if( !this.changed.getAndSet( true ) && this.onChanged != null ) + { this.onChanged.run(); } } - public boolean isOpen(int channel) { - synchronized (this.channels) { - return this.channels.contains(channel); + public boolean isOpen( int channel ) + { + synchronized( this.channels ) + { + return this.channels.contains( channel ); } } - public void open(int channel) throws LuaException { - synchronized (this.channels) { - if (!this.channels.contains(channel)) { - if (this.channels.size() >= 128) { - throw new LuaException("Too many open channels"); + public void open( int channel ) throws LuaException + { + synchronized( this.channels ) + { + if( !this.channels.contains( channel ) ) + { + if( this.channels.size() >= 128 ) + { + throw new LuaException( "Too many open channels" ); } - this.channels.add(channel); - this.setOpen(true); + this.channels.add( channel ); + this.setOpen( true ); } } } - public void close(int channel) { - synchronized (this.channels) { - this.channels.remove(channel); - if (this.channels.isEmpty()) { - this.setOpen(false); + public void close( int channel ) + { + synchronized( this.channels ) + { + this.channels.remove( channel ); + if( this.channels.isEmpty() ) + { + this.setOpen( false ); } } } - public void closeAll() { - synchronized (this.channels) { + public void closeAll() + { + synchronized( this.channels ) + { this.channels.clear(); - this.setOpen(false); + this.setOpen( false ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java index 7b6fde27d..4e958b69c 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java @@ -6,21 +6,10 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED; -import static dan200.computercraft.shared.util.WaterloggableHelpers.getWaterloggedFluidState; -import static dan200.computercraft.shared.util.WaterloggableHelpers.getWaterloggedStateForPlacement; -import static dan200.computercraft.shared.util.WaterloggableHelpers.updateWaterloggedPostPlacement; - -import java.util.EnumMap; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.collect.ImmutableMap; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.ShapeContext; @@ -41,81 +30,96 @@ import net.minecraft.world.World; import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldView; -public class BlockCable extends BlockGeneric implements Waterloggable { - public static final EnumProperty MODEM = EnumProperty.of("modem", CableModemVariant.class); - public static final BooleanProperty CABLE = BooleanProperty.of("cable"); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.EnumMap; - private static final BooleanProperty NORTH = BooleanProperty.of("north"); - private static final BooleanProperty SOUTH = BooleanProperty.of("south"); - private static final BooleanProperty EAST = BooleanProperty.of("east"); - private static final BooleanProperty WEST = BooleanProperty.of("west"); - private static final BooleanProperty UP = BooleanProperty.of("up"); - private static final BooleanProperty DOWN = BooleanProperty.of("down"); +import static dan200.computercraft.shared.util.WaterloggableHelpers.*; - static final EnumMap CONNECTIONS = new EnumMap<>(new ImmutableMap.Builder().put(Direction.DOWN, - DOWN) - .put(Direction.UP, - UP) - .put(Direction.NORTH, - NORTH) - .put(Direction.SOUTH, - SOUTH) - .put(Direction.WEST, - WEST) - .put(Direction.EAST, - EAST) - .build()); +public class BlockCable extends BlockGeneric implements Waterloggable +{ + public static final EnumProperty MODEM = EnumProperty.of( "modem", CableModemVariant.class ); + public static final BooleanProperty CABLE = BooleanProperty.of( "cable" ); - public BlockCable(Settings settings) { - super(settings, ComputerCraftRegistry.ModTiles.CABLE); + private static final BooleanProperty NORTH = BooleanProperty.of( "north" ); + private static final BooleanProperty SOUTH = BooleanProperty.of( "south" ); + private static final BooleanProperty EAST = BooleanProperty.of( "east" ); + private static final BooleanProperty WEST = BooleanProperty.of( "west" ); + private static final BooleanProperty UP = BooleanProperty.of( "up" ); + private static final BooleanProperty DOWN = BooleanProperty.of( "down" ); - this.setDefaultState(this.getStateManager().getDefaultState() - .with(MODEM, CableModemVariant.None) - .with(CABLE, false) - .with(NORTH, false) - .with(SOUTH, false) - .with(EAST, false) - .with(WEST, false) - .with(UP, false) - .with(DOWN, false) - .with(WATERLOGGED, false)); + static final EnumMap CONNECTIONS = new EnumMap<>( new ImmutableMap.Builder().put( Direction.DOWN, + DOWN ) + .put( Direction.UP, + UP ) + .put( Direction.NORTH, + NORTH ) + .put( Direction.SOUTH, + SOUTH ) + .put( Direction.WEST, + WEST ) + .put( Direction.EAST, + EAST ) + .build() ); + + public BlockCable( Settings settings ) + { + super( settings, ComputerCraftRegistry.ModTiles.CABLE ); + + this.setDefaultState( this.getStateManager().getDefaultState() + .with( MODEM, CableModemVariant.None ) + .with( CABLE, false ) + .with( NORTH, false ) + .with( SOUTH, false ) + .with( EAST, false ) + .with( WEST, false ) + .with( UP, false ) + .with( DOWN, false ) + .with( WATERLOGGED, false ) ); } - public static boolean canConnectIn(BlockState state, Direction direction) { - return state.get(BlockCable.CABLE) && state.get(BlockCable.MODEM) - .getFacing() != direction; + public static boolean canConnectIn( BlockState state, Direction direction ) + { + return state.get( BlockCable.CABLE ) && state.get( BlockCable.MODEM ) + .getFacing() != direction; } @Nonnull @Override @Deprecated - public BlockState getStateForNeighborUpdate(@Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, - @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos) { - updateWaterloggedPostPlacement(state, world, pos); + public BlockState getStateForNeighborUpdate( @Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, + @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos ) + { + updateWaterloggedPostPlacement( state, world, pos ); // Should never happen, but handle the case where we've no modem or cable. - if (!state.get(CABLE) && state.get(MODEM) == CableModemVariant.None) { - return this.getFluidState(state).getBlockState(); + if( !state.get( CABLE ) && state.get( MODEM ) == CableModemVariant.None ) + { + return this.getFluidState( state ).getBlockState(); } - return state.with(CONNECTIONS.get(side), doesConnectVisually(state, world, pos, side)); + return state.with( CONNECTIONS.get( side ), doesConnectVisually( state, world, pos, side ) ); } - public static boolean doesConnectVisually(BlockState state, BlockView world, BlockPos pos, Direction direction) { - if (!state.get(CABLE)) { + public static boolean doesConnectVisually( BlockState state, BlockView world, BlockPos pos, Direction direction ) + { + if( !state.get( CABLE ) ) + { return false; } - if (state.get(MODEM) - .getFacing() == direction) { + if( state.get( MODEM ) + .getFacing() == direction ) + { return true; } - return ComputerCraftAPI.getWiredElementAt(world, pos.offset(direction), direction.getOpposite()) != null; + return ComputerCraftAPI.getWiredElementAt( world, pos.offset( direction ), direction.getOpposite() ) != null; } @Nonnull @Override @Deprecated - public FluidState getFluidState(@Nonnull BlockState state) { - return getWaterloggedFluidState(state); + public FluidState getFluidState( @Nonnull BlockState state ) + { + return getWaterloggedFluidState( state ); } // @Override @@ -183,73 +187,88 @@ public class BlockCable extends BlockGeneric implements Waterloggable { @Override @Deprecated - public boolean canPlaceAt(BlockState state, @Nonnull WorldView world, @Nonnull BlockPos pos) { - Direction facing = state.get(MODEM) - .getFacing(); - if (facing == null) { + public boolean canPlaceAt( BlockState state, @Nonnull WorldView world, @Nonnull BlockPos pos ) + { + Direction facing = state.get( MODEM ) + .getFacing(); + if( facing == null ) + { return true; } - return sideCoversSmallSquare(world, pos.offset(facing), facing.getOpposite()); + return sideCoversSmallSquare( world, pos.offset( facing ), facing.getOpposite() ); } @Nonnull @Override @Deprecated - public VoxelShape getOutlineShape(@Nonnull BlockState state, @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull ShapeContext context) { - return CableShapes.getShape(state); + public VoxelShape getOutlineShape( @Nonnull BlockState state, @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull ShapeContext context ) + { + return CableShapes.getShape( state ); } @Nullable @Override - public BlockState getPlacementState(@Nonnull ItemPlacementContext context) { - BlockState state = this.getDefaultState().with(WATERLOGGED, getWaterloggedStateForPlacement(context)); + public BlockState getPlacementState( @Nonnull ItemPlacementContext context ) + { + BlockState state = this.getDefaultState().with( WATERLOGGED, getWaterloggedStateForPlacement( context ) ); - if (context.getStack() - .getItem() instanceof ItemBlockCable.Cable) { + if( context.getStack() + .getItem() instanceof ItemBlockCable.Cable ) + { World world = context.getWorld(); BlockPos pos = context.getBlockPos(); - return correctConnections(world, pos, state.with(CABLE, true)); - } else { - return state.with(MODEM, - CableModemVariant.from(context.getSide() - .getOpposite())); + return correctConnections( world, pos, state.with( CABLE, true ) ); + } + else + { + return state.with( MODEM, + CableModemVariant.from( context.getSide() + .getOpposite() ) ); } } @Override - public void onPlaced(World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack) { - BlockEntity tile = world.getBlockEntity(pos); - if (tile instanceof TileCable) { + public void onPlaced( World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack ) + { + BlockEntity tile = world.getBlockEntity( pos ); + if( tile instanceof TileCable ) + { TileCable cable = (TileCable) tile; - if (cable.hasCable()) { + if( cable.hasCable() ) + { cable.connectionsChanged(); } } - super.onPlaced(world, pos, state, placer, stack); + super.onPlaced( world, pos, state, placer, stack ); } @Override - protected void appendProperties(StateManager.Builder builder) { - builder.add(MODEM, CABLE, NORTH, SOUTH, EAST, WEST, UP, DOWN, WATERLOGGED); + protected void appendProperties( StateManager.Builder builder ) + { + builder.add( MODEM, CABLE, NORTH, SOUTH, EAST, WEST, UP, DOWN, WATERLOGGED ); } - public static BlockState correctConnections(World world, BlockPos pos, BlockState state) { - if (state.get(CABLE)) { - return state.with(NORTH, doesConnectVisually(state, world, pos, Direction.NORTH)) - .with(SOUTH, doesConnectVisually(state, world, pos, Direction.SOUTH)) - .with(EAST, doesConnectVisually(state, world, pos, Direction.EAST)) - .with(WEST, doesConnectVisually(state, world, pos, Direction.WEST)) - .with(UP, doesConnectVisually(state, world, pos, Direction.UP)) - .with(DOWN, doesConnectVisually(state, world, pos, Direction.DOWN)); - } else { - return state.with(NORTH, false) - .with(SOUTH, false) - .with(EAST, false) - .with(WEST, false) - .with(UP, false) - .with(DOWN, false); + public static BlockState correctConnections( World world, BlockPos pos, BlockState state ) + { + if( state.get( CABLE ) ) + { + return state.with( NORTH, doesConnectVisually( state, world, pos, Direction.NORTH ) ) + .with( SOUTH, doesConnectVisually( state, world, pos, Direction.SOUTH ) ) + .with( EAST, doesConnectVisually( state, world, pos, Direction.EAST ) ) + .with( WEST, doesConnectVisually( state, world, pos, Direction.WEST ) ) + .with( UP, doesConnectVisually( state, world, pos, Direction.UP ) ) + .with( DOWN, doesConnectVisually( state, world, pos, Direction.DOWN ) ); + } + else + { + return state.with( NORTH, false ) + .with( SOUTH, false ) + .with( EAST, false ) + .with( WEST, false ) + .with( UP, false ) + .with( DOWN, false ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java index fa801daf1..fc6572cc3 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java @@ -7,26 +7,28 @@ package dan200.computercraft.shared.peripheral.modem.wired; import dan200.computercraft.shared.common.BlockGeneric; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.state.StateManager; import net.minecraft.state.property.BooleanProperty; -public class BlockWiredModemFull extends BlockGeneric { - public static final BooleanProperty MODEM_ON = BooleanProperty.of("modem"); - public static final BooleanProperty PERIPHERAL_ON = BooleanProperty.of("peripheral"); +public class BlockWiredModemFull extends BlockGeneric +{ + public static final BooleanProperty MODEM_ON = BooleanProperty.of( "modem" ); + public static final BooleanProperty PERIPHERAL_ON = BooleanProperty.of( "peripheral" ); - public BlockWiredModemFull(Settings settings, BlockEntityType type) { - super(settings, type); - this.setDefaultState(this.getStateManager().getDefaultState() - .with(MODEM_ON, false) - .with(PERIPHERAL_ON, false)); + public BlockWiredModemFull( Settings settings, BlockEntityType type ) + { + super( settings, type ); + this.setDefaultState( this.getStateManager().getDefaultState() + .with( MODEM_ON, false ) + .with( PERIPHERAL_ON, false ) ); } @Override - protected void appendProperties(StateManager.Builder builder) { - builder.add(MODEM_ON, PERIPHERAL_ON); + protected void appendProperties( StateManager.Builder builder ) + { + builder.add( MODEM_ON, PERIPHERAL_ON ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableModemVariant.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableModemVariant.java index 0c3c16e8c..5c6fc398d 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableModemVariant.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableModemVariant.java @@ -6,73 +6,80 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import net.minecraft.util.StringIdentifiable; import net.minecraft.util.math.Direction; -public enum CableModemVariant implements StringIdentifiable { - None("none", null), - DownOff("down_off", Direction.DOWN), - UpOff("up_off", Direction.UP), - NorthOff("north_off", Direction.NORTH), - SouthOff("south_off", Direction.SOUTH), - WestOff("west_off", Direction.WEST), - EastOff("east_off", Direction.EAST), - DownOn("down_on", Direction.DOWN), - UpOn("up_on", Direction.UP), - NorthOn("north_on", Direction.NORTH), - SouthOn("south_on", Direction.SOUTH), - WestOn("west_on", Direction.WEST), - EastOn("east_on", Direction.EAST), - DownOffPeripheral("down_off_peripheral", Direction.DOWN), - UpOffPeripheral("up_off_peripheral", Direction.UP), - NorthOffPeripheral("north_off_peripheral", Direction.NORTH), - SouthOffPeripheral("south_off_peripheral", Direction.SOUTH), - WestOffPeripheral("west_off_peripheral", Direction.WEST), - EastOffPeripheral("east_off_peripheral", Direction.EAST), - DownOnPeripheral("down_on_peripheral", Direction.DOWN), - UpOnPeripheral("up_on_peripheral", Direction.UP), - NorthOnPeripheral("north_on_peripheral", Direction.NORTH), - SouthOnPeripheral("south_on_peripheral", Direction.SOUTH), - WestOnPeripheral("west_on_peripheral", Direction.WEST), - EastOnPeripheral("east_on_peripheral", Direction.EAST); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public enum CableModemVariant implements StringIdentifiable +{ + None( "none", null ), + DownOff( "down_off", Direction.DOWN ), + UpOff( "up_off", Direction.UP ), + NorthOff( "north_off", Direction.NORTH ), + SouthOff( "south_off", Direction.SOUTH ), + WestOff( "west_off", Direction.WEST ), + EastOff( "east_off", Direction.EAST ), + DownOn( "down_on", Direction.DOWN ), + UpOn( "up_on", Direction.UP ), + NorthOn( "north_on", Direction.NORTH ), + SouthOn( "south_on", Direction.SOUTH ), + WestOn( "west_on", Direction.WEST ), + EastOn( "east_on", Direction.EAST ), + DownOffPeripheral( "down_off_peripheral", Direction.DOWN ), + UpOffPeripheral( "up_off_peripheral", Direction.UP ), + NorthOffPeripheral( "north_off_peripheral", Direction.NORTH ), + SouthOffPeripheral( "south_off_peripheral", Direction.SOUTH ), + WestOffPeripheral( "west_off_peripheral", Direction.WEST ), + EastOffPeripheral( "east_off_peripheral", Direction.EAST ), + DownOnPeripheral( "down_on_peripheral", Direction.DOWN ), + UpOnPeripheral( "up_on_peripheral", Direction.UP ), + NorthOnPeripheral( "north_on_peripheral", Direction.NORTH ), + SouthOnPeripheral( "south_on_peripheral", Direction.SOUTH ), + WestOnPeripheral( "west_on_peripheral", Direction.WEST ), + EastOnPeripheral( "east_on_peripheral", Direction.EAST ); private static final CableModemVariant[] VALUES = values(); private final String name; private final Direction facing; - CableModemVariant(String name, Direction facing) { + CableModemVariant( String name, Direction facing ) + { this.name = name; this.facing = facing; } @Nonnull - public static CableModemVariant from(Direction facing) { + public static CableModemVariant from( Direction facing ) + { return facing == null ? None : VALUES[1 + facing.getId()]; } @Nonnull - public static CableModemVariant from(Direction facing, boolean modem, boolean peripheral) { + public static CableModemVariant from( Direction facing, boolean modem, boolean peripheral ) + { int state = (modem ? 2 : 0) + (peripheral ? 1 : 0); return facing == null ? None : VALUES[1 + 6 * state + facing.getId()]; } @Nonnull @Override - public String asString() { + public String asString() + { return this.name; } @Nullable - public Direction getFacing() { + public Direction getFacing() + { return this.facing; } @Override - public String toString() { + public String toString() + { return this.name; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableShapes.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableShapes.java index 85a6112fc..12bd696cb 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableShapes.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableShapes.java @@ -6,110 +6,118 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.CABLE; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.CONNECTIONS; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.MODEM; - -import java.util.EnumMap; - import com.google.common.collect.ImmutableMap; import dan200.computercraft.shared.peripheral.modem.ModemShapes; import dan200.computercraft.shared.util.DirectionUtil; - import net.minecraft.block.BlockState; import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; -public final class CableShapes { +import java.util.EnumMap; + +import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.*; + +public final class CableShapes +{ private static final double MIN = 0.375; private static final double MAX = 1 - MIN; - private static final VoxelShape SHAPE_CABLE_CORE = VoxelShapes.cuboid(MIN, MIN, MIN, MAX, MAX, MAX); + private static final VoxelShape SHAPE_CABLE_CORE = VoxelShapes.cuboid( MIN, MIN, MIN, MAX, MAX, MAX ); private static final EnumMap SHAPE_CABLE_ARM = - new EnumMap<>(new ImmutableMap.Builder().put(Direction.DOWN, - VoxelShapes.cuboid( - MIN, - 0, - MIN, - MAX, - MIN, - MAX)) - .put(Direction.UP, - VoxelShapes.cuboid( - MIN, - MAX, - MIN, - MAX, - 1, - MAX)) - .put(Direction.NORTH, - VoxelShapes.cuboid( - MIN, - MIN, - 0, - MAX, - MAX, - MIN)) - .put(Direction.SOUTH, - VoxelShapes.cuboid( - MIN, - MIN, - MAX, - MAX, - MAX, - 1)) - .put(Direction.WEST, - VoxelShapes.cuboid( - 0, - MIN, - MIN, - MIN, - MAX, - MAX)) - .put(Direction.EAST, - VoxelShapes.cuboid( - MAX, - MIN, - MIN, - 1, - MAX, - MAX)) - .build()); + new EnumMap<>( new ImmutableMap.Builder().put( Direction.DOWN, + VoxelShapes.cuboid( + MIN, + 0, + MIN, + MAX, + MIN, + MAX ) ) + .put( Direction.UP, + VoxelShapes.cuboid( + MIN, + MAX, + MIN, + MAX, + 1, + MAX ) ) + .put( Direction.NORTH, + VoxelShapes.cuboid( + MIN, + MIN, + 0, + MAX, + MAX, + MIN ) ) + .put( Direction.SOUTH, + VoxelShapes.cuboid( + MIN, + MIN, + MAX, + MAX, + MAX, + 1 ) ) + .put( Direction.WEST, + VoxelShapes.cuboid( + 0, + MIN, + MIN, + MIN, + MAX, + MAX ) ) + .put( Direction.EAST, + VoxelShapes.cuboid( + MAX, + MIN, + MIN, + 1, + MAX, + MAX ) ) + .build() ); private static final VoxelShape[] SHAPES = new VoxelShape[(1 << 6) * 7]; private static final VoxelShape[] CABLE_SHAPES = new VoxelShape[1 << 6]; - private CableShapes() { + private CableShapes() + { } - public static VoxelShape getCableShape(BlockState state) { - if (!state.get(CABLE)) { + public static VoxelShape getCableShape( BlockState state ) + { + if( !state.get( CABLE ) ) + { return VoxelShapes.empty(); } - return getCableShape(getCableIndex(state)); + return getCableShape( getCableIndex( state ) ); } - private static VoxelShape getCableShape(int index) { + private static VoxelShape getCableShape( int index ) + { VoxelShape shape = CABLE_SHAPES[index]; - if (shape != null) { + if( shape != null ) + { return shape; } shape = SHAPE_CABLE_CORE; - for (Direction facing : DirectionUtil.FACINGS) { - if ((index & (1 << facing.ordinal())) != 0) { - shape = VoxelShapes.union(shape, SHAPE_CABLE_ARM.get(facing)); + for( Direction facing : DirectionUtil.FACINGS ) + { + if( (index & (1 << facing.ordinal())) != 0 ) + { + shape = VoxelShapes.union( shape, SHAPE_CABLE_ARM.get( facing ) ); } } return CABLE_SHAPES[index] = shape; } - private static int getCableIndex(BlockState state) { + private static int getCableIndex( BlockState state ) + { int index = 0; - for (Direction facing : DirectionUtil.FACINGS) { - if (state.get(CONNECTIONS.get(facing))) { + for( Direction facing : DirectionUtil.FACINGS ) + { + if( state.get( CONNECTIONS.get( facing ) ) ) + { index |= 1 << facing.ordinal(); } } @@ -117,31 +125,36 @@ public final class CableShapes { return index; } - public static VoxelShape getShape(BlockState state) { - Direction facing = state.get(MODEM) - .getFacing(); - if (!state.get(CABLE)) { - return getModemShape(state); + public static VoxelShape getShape( BlockState state ) + { + Direction facing = state.get( MODEM ) + .getFacing(); + if( !state.get( CABLE ) ) + { + return getModemShape( state ); } - int cableIndex = getCableIndex(state); + int cableIndex = getCableIndex( state ); int index = cableIndex + ((facing == null ? 0 : facing.ordinal() + 1) << 6); VoxelShape shape = SHAPES[index]; - if (shape != null) { + if( shape != null ) + { return shape; } - shape = getCableShape(cableIndex); - if (facing != null) { - shape = VoxelShapes.union(shape, ModemShapes.getBounds(facing)); + shape = getCableShape( cableIndex ); + if( facing != null ) + { + shape = VoxelShapes.union( shape, ModemShapes.getBounds( facing ) ); } return SHAPES[index] = shape; } - public static VoxelShape getModemShape(BlockState state) { - Direction facing = state.get(MODEM) - .getFacing(); - return facing == null ? VoxelShapes.empty() : ModemShapes.getBounds(facing); + public static VoxelShape getModemShape( BlockState state ) + { + Direction facing = state.get( MODEM ) + .getFacing(); + return facing == null ? VoxelShapes.empty() : ModemShapes.getBounds( facing ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java index 4685c18a3..d866b41c7 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java @@ -6,15 +6,7 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.CABLE; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.CONNECTIONS; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.MODEM; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.correctConnections; - -import javax.annotation.Nonnull; - import dan200.computercraft.shared.ComputerCraftRegistry; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; @@ -32,30 +24,40 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.registry.Registry; import net.minecraft.world.World; -public abstract class ItemBlockCable extends BlockItem { +import javax.annotation.Nonnull; + +import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.*; + +public abstract class ItemBlockCable extends BlockItem +{ private String translationKey; - public ItemBlockCable(BlockCable block, Settings settings) { - super(block, settings); + public ItemBlockCable( BlockCable block, Settings settings ) + { + super( block, settings ); } - boolean placeAtCorrected(World world, BlockPos pos, BlockState state) { - return this.placeAt(world, pos, correctConnections(world, pos, state), null); + boolean placeAtCorrected( World world, BlockPos pos, BlockState state ) + { + return this.placeAt( world, pos, correctConnections( world, pos, state ), null ); } - boolean placeAt(World world, BlockPos pos, BlockState state, PlayerEntity player) { + boolean placeAt( World world, BlockPos pos, BlockState state, PlayerEntity player ) + { // TODO: Check entity collision. - if (!state.canPlaceAt(world, pos)) { + if( !state.canPlaceAt( world, pos ) ) + { return false; } - world.setBlockState(pos, state, 3); + world.setBlockState( pos, state, 3 ); BlockSoundGroup soundType = state.getBlock() - .getSoundGroup(state); - world.playSound(null, pos, soundType.getPlaceSound(), SoundCategory.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F); + .getSoundGroup( state ); + world.playSound( null, pos, soundType.getPlaceSound(), SoundCategory.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F ); - BlockEntity tile = world.getBlockEntity(pos); - if (tile instanceof TileCable) { + BlockEntity tile = world.getBlockEntity( pos ); + if( tile instanceof TileCable ) + { TileCable cable = (TileCable) tile; cable.modemChanged(); cable.connectionsChanged(); @@ -66,63 +68,77 @@ public abstract class ItemBlockCable extends BlockItem { @Nonnull @Override - public String getTranslationKey() { - if (this.translationKey == null) { - this.translationKey = Util.createTranslationKey("block", Registry.ITEM.getId(this)); + public String getTranslationKey() + { + if( this.translationKey == null ) + { + this.translationKey = Util.createTranslationKey( "block", Registry.ITEM.getId( this ) ); } return this.translationKey; } @Override - public void appendStacks(@Nonnull ItemGroup group, @Nonnull DefaultedList list) { - if (this.isIn(group)) { - list.add(new ItemStack(this)); + public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList list ) + { + if( this.isIn( group ) ) + { + list.add( new ItemStack( this ) ); } } - public static class WiredModem extends ItemBlockCable { - public WiredModem(BlockCable block, Settings settings) { - super(block, settings); + public static class WiredModem extends ItemBlockCable + { + public WiredModem( BlockCable block, Settings settings ) + { + super( block, settings ); } @Nonnull @Override - public ActionResult place(ItemPlacementContext context) { + public ActionResult place( ItemPlacementContext context ) + { ItemStack stack = context.getStack(); - if (stack.isEmpty()) { + if( stack.isEmpty() ) + { return ActionResult.FAIL; } World world = context.getWorld(); BlockPos pos = context.getBlockPos(); - BlockState existingState = world.getBlockState(pos); + BlockState existingState = world.getBlockState( pos ); // Try to add a modem to a cable - if (existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && existingState.get(MODEM) == CableModemVariant.None) { + if( existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && existingState.get( MODEM ) == CableModemVariant.None ) + { Direction side = context.getSide() - .getOpposite(); - BlockState newState = existingState.with(MODEM, CableModemVariant.from(side)) - .with(CONNECTIONS.get(side), existingState.get(CABLE)); - if (this.placeAt(world, pos, newState, context.getPlayer())) { - stack.decrement(1); + .getOpposite(); + BlockState newState = existingState.with( MODEM, CableModemVariant.from( side ) ) + .with( CONNECTIONS.get( side ), existingState.get( CABLE ) ); + if( this.placeAt( world, pos, newState, context.getPlayer() ) ) + { + stack.decrement( 1 ); return ActionResult.SUCCESS; } } - return super.place(context); + return super.place( context ); } } - public static class Cable extends ItemBlockCable { - public Cable(BlockCable block, Settings settings) { - super(block, settings); + public static class Cable extends ItemBlockCable + { + public Cable( BlockCable block, Settings settings ) + { + super( block, settings ); } @Nonnull @Override - public ActionResult place(ItemPlacementContext context) { + public ActionResult place( ItemPlacementContext context ) + { ItemStack stack = context.getStack(); - if (stack.isEmpty()) { + if( stack.isEmpty() ) + { return ActionResult.FAIL; } @@ -130,30 +146,32 @@ public abstract class ItemBlockCable extends BlockItem { BlockPos pos = context.getBlockPos(); // Try to add a cable to a modem inside the block we're clicking on. - BlockPos insidePos = pos.offset(context.getSide() - .getOpposite()); - BlockState insideState = world.getBlockState(insidePos); - if (insideState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !insideState.get(BlockCable.CABLE) && this.placeAtCorrected(world, - insidePos, - insideState.with( - BlockCable.CABLE, - true))) { - stack.decrement(1); + BlockPos insidePos = pos.offset( context.getSide() + .getOpposite() ); + BlockState insideState = world.getBlockState( insidePos ); + if( insideState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !insideState.get( BlockCable.CABLE ) && this.placeAtCorrected( world, + insidePos, + insideState.with( + BlockCable.CABLE, + true ) ) ) + { + stack.decrement( 1 ); return ActionResult.SUCCESS; } // Try to add a cable to a modem adjacent to this block - BlockState existingState = world.getBlockState(pos); - if (existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !existingState.get(BlockCable.CABLE) && this.placeAtCorrected(world, - pos, - existingState.with( - BlockCable.CABLE, - true))) { - stack.decrement(1); + BlockState existingState = world.getBlockState( pos ); + if( existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !existingState.get( BlockCable.CABLE ) && this.placeAtCorrected( world, + pos, + existingState.with( + BlockCable.CABLE, + true ) ) ) + { + stack.decrement( 1 ); return ActionResult.SUCCESS; } - return super.place(context); + return super.place( context ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java index 9b23eaed7..fe4440f24 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java @@ -6,12 +6,6 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import java.util.Collections; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.base.Objects; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.network.wired.IWiredElement; @@ -24,7 +18,6 @@ import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.peripheral.modem.ModemState; import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.TickScheduler; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; @@ -40,7 +33,13 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class TileCable extends TileGeneric implements IPeripheralTile { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.Map; + +public class TileCable extends TileGeneric implements IPeripheralTile +{ private static final String NBT_PERIPHERAL_ENABLED = "PeirpheralAccess"; private final WiredModemLocalPeripheral m_peripheral = new WiredModemLocalPeripheral(); private final WiredModemElement m_cable = new CableElement(); @@ -48,35 +47,43 @@ public class TileCable extends TileGeneric implements IPeripheralTile { private boolean m_peripheralAccessAllowed; private boolean m_destroyed = false; private Direction modemDirection = Direction.NORTH; - private final WiredModemPeripheral m_modem = new WiredModemPeripheral(new ModemState(() -> TickScheduler.schedule(this)), this.m_cable) { + private final WiredModemPeripheral m_modem = new WiredModemPeripheral( new ModemState( () -> TickScheduler.schedule( this ) ), this.m_cable ) + { @Nonnull @Override - protected WiredModemLocalPeripheral getLocalPeripheral() { + protected WiredModemLocalPeripheral getLocalPeripheral() + { return TileCable.this.m_peripheral; } @Nonnull @Override - public Vec3d getPosition() { - BlockPos pos = TileCable.this.getPos().offset(TileCable.this.modemDirection); - return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + public Vec3d getPosition() + { + BlockPos pos = TileCable.this.getPos().offset( TileCable.this.modemDirection ); + return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); } @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return TileCable.this; } }; private boolean hasModemDirection = false; private boolean m_connectionsFormed = false; - public TileCable(BlockEntityType type) { - super(type); + + public TileCable( BlockEntityType type ) + { + super( type ); } @Override - public void destroy() { - if (!this.m_destroyed) { + public void destroy() + { + if( !this.m_destroyed ) + { this.m_destroyed = true; this.m_modem.destroy(); this.onRemove(); @@ -90,8 +97,10 @@ public class TileCable extends TileGeneric implements IPeripheralTile { onRemove(); } - private void onRemove() { - if (this.world == null || !this.world.isClient) { + private void onRemove() + { + if( this.world == null || !this.world.isClient ) + { this.m_node.remove(); this.m_connectionsFormed = false; } @@ -99,29 +108,36 @@ public class TileCable extends TileGeneric implements IPeripheralTile { @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - if (player.isInSneakingPose()) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + if( player.isInSneakingPose() ) + { return ActionResult.PASS; } - if (!this.canAttachPeripheral()) { + if( !this.canAttachPeripheral() ) + { return ActionResult.FAIL; } - if (this.getWorld().isClient) { + if( this.getWorld().isClient ) + { return ActionResult.SUCCESS; } String oldName = this.m_peripheral.getConnectedName(); this.togglePeripheralAccess(); String newName = this.m_peripheral.getConnectedName(); - if (!Objects.equal(newName, oldName)) { - if (oldName != null) { - player.sendMessage(new TranslatableText("chat.computercraft.wired_modem.peripheral_disconnected", - ChatHelpers.copy(oldName)), false); + if( !Objects.equal( newName, oldName ) ) + { + if( oldName != null ) + { + player.sendMessage( new TranslatableText( "chat.computercraft.wired_modem.peripheral_disconnected", + ChatHelpers.copy( oldName ) ), false ); } - if (newName != null) { - player.sendMessage(new TranslatableText("chat.computercraft.wired_modem.peripheral_connected", - ChatHelpers.copy(newName)), false); + if( newName != null ) + { + player.sendMessage( new TranslatableText( "chat.computercraft.wired_modem.peripheral_connected", + ChatHelpers.copy( newName ) ), false ); } } @@ -129,264 +145,320 @@ public class TileCable extends TileGeneric implements IPeripheralTile { } @Override - public void onNeighbourChange(@Nonnull BlockPos neighbour) { + public void onNeighbourChange( @Nonnull BlockPos neighbour ) + { Direction dir = this.getDirection(); - if (neighbour.equals(this.getPos().offset(dir)) && this.hasModem() && !this.getCachedState().canPlaceAt(this.getWorld(), this.getPos())) { - if (this.hasCable()) { + if( neighbour.equals( this.getPos().offset( dir ) ) && this.hasModem() && !this.getCachedState().canPlaceAt( this.getWorld(), this.getPos() ) ) + { + if( this.hasCable() ) + { // Drop the modem and convert to cable - Block.dropStack(this.getWorld(), this.getPos(), new ItemStack(ComputerCraftRegistry.ModItems.WIRED_MODEM)); - this.getWorld().setBlockState(this.getPos(), - this.getCachedState().with(BlockCable.MODEM, CableModemVariant.None)); + Block.dropStack( this.getWorld(), this.getPos(), new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM ) ); + this.getWorld().setBlockState( this.getPos(), + this.getCachedState().with( BlockCable.MODEM, CableModemVariant.None ) ); this.modemChanged(); this.connectionsChanged(); - } else { + } + else + { // Drop everything and remove block - Block.dropStack(this.getWorld(), this.getPos(), new ItemStack(ComputerCraftRegistry.ModItems.WIRED_MODEM)); - this.getWorld().removeBlock(this.getPos(), false); + Block.dropStack( this.getWorld(), this.getPos(), new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM ) ); + this.getWorld().removeBlock( this.getPos(), false ); // This'll call #destroy(), so we don't need to reset the network here. } return; } - this.onNeighbourTileEntityChange(neighbour); + this.onNeighbourTileEntityChange( neighbour ); } @Nonnull - private Direction getDirection() { + private Direction getDirection() + { this.refreshDirection(); return this.modemDirection == null ? Direction.NORTH : this.modemDirection; } - public boolean hasModem() { - return this.getCachedState().get(BlockCable.MODEM) != CableModemVariant.None; + public boolean hasModem() + { + return this.getCachedState().get( BlockCable.MODEM ) != CableModemVariant.None; } - boolean hasCable() { - return this.getCachedState().get(BlockCable.CABLE); + boolean hasCable() + { + return this.getCachedState().get( BlockCable.CABLE ); } - void modemChanged() { + void modemChanged() + { // Tell anyone who cares that the connection state has changed - if (this.getWorld().isClient) { + if( this.getWorld().isClient ) + { return; } // If we can no longer attach peripherals, then detach any // which may have existed - if (!this.canAttachPeripheral() && this.m_peripheralAccessAllowed) { + if( !this.canAttachPeripheral() && this.m_peripheralAccessAllowed ) + { this.m_peripheralAccessAllowed = false; this.m_peripheral.detach(); - this.m_node.updatePeripherals(Collections.emptyMap()); + this.m_node.updatePeripherals( Collections.emptyMap() ); this.markDirty(); this.updateBlockState(); } } - void connectionsChanged() { - if (this.getWorld().isClient) { + void connectionsChanged() + { + if( this.getWorld().isClient ) + { return; } BlockState state = this.getCachedState(); World world = this.getWorld(); BlockPos current = this.getPos(); - for (Direction facing : DirectionUtil.FACINGS) { - BlockPos offset = current.offset(facing); - if (!world.isChunkLoaded(offset)) { + for( Direction facing : DirectionUtil.FACINGS ) + { + BlockPos offset = current.offset( facing ); + if( !world.isChunkLoaded( offset ) ) + { continue; } - IWiredElement element = ComputerCraftAPI.getWiredElementAt(world, offset, facing.getOpposite()); - if (element != null) { + IWiredElement element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); + if( element != null ) + { // TODO Figure out why this crashes. IWiredNode node = element.getNode(); - if (node != null && this.m_node != null) { - if (BlockCable.canConnectIn(state, facing)) { + if( node != null && this.m_node != null ) + { + if( BlockCable.canConnectIn( state, facing ) ) + { // If we can connect to it then do so - this.m_node.connectTo(node); - } else if (this.m_node.getNetwork() == node.getNetwork()) { + this.m_node.connectTo( node ); + } + else if( this.m_node.getNetwork() == node.getNetwork() ) + { // Otherwise if we're on the same network then attempt to void it. - this.m_node.disconnectFrom(node); + this.m_node.disconnectFrom( node ); } } } } } - private boolean canAttachPeripheral() { + private boolean canAttachPeripheral() + { return this.hasCable() && this.hasModem(); } - private void updateBlockState() { + private void updateBlockState() + { BlockState state = this.getCachedState(); - CableModemVariant oldVariant = state.get(BlockCable.MODEM); - CableModemVariant newVariant = CableModemVariant.from(oldVariant.getFacing(), this.m_modem.getModemState() - .isOpen(), this.m_peripheralAccessAllowed); + CableModemVariant oldVariant = state.get( BlockCable.MODEM ); + CableModemVariant newVariant = CableModemVariant.from( oldVariant.getFacing(), this.m_modem.getModemState() + .isOpen(), this.m_peripheralAccessAllowed ); - if (oldVariant != newVariant) { - this.world.setBlockState(this.getPos(), state.with(BlockCable.MODEM, newVariant)); + if( oldVariant != newVariant ) + { + this.world.setBlockState( this.getPos(), state.with( BlockCable.MODEM, newVariant ) ); } } - private void refreshPeripheral() { - if (this.world != null && !this.isRemoved() && this.m_peripheral.attach(this.world, this.getPos(), this.getDirection())) { + private void refreshPeripheral() + { + if( this.world != null && !this.isRemoved() && this.m_peripheral.attach( this.world, this.getPos(), this.getDirection() ) ) + { this.updateConnectedPeripherals(); } } - private void updateConnectedPeripherals() { + private void updateConnectedPeripherals() + { Map peripherals = this.m_peripheral.toMap(); - if (peripherals.isEmpty()) { + if( peripherals.isEmpty() ) + { // If there are no peripherals then disable access and update the display state. this.m_peripheralAccessAllowed = false; this.updateBlockState(); } - this.m_node.updatePeripherals(peripherals); + this.m_node.updatePeripherals( peripherals ); } @Override - public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) { - super.onNeighbourTileEntityChange(neighbour); - if (!this.world.isClient && this.m_peripheralAccessAllowed) { + public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) + { + super.onNeighbourTileEntityChange( neighbour ); + if( !this.world.isClient && this.m_peripheralAccessAllowed ) + { Direction facing = this.getDirection(); - if (this.getPos().offset(facing) - .equals(neighbour)) { + if( this.getPos().offset( facing ) + .equals( neighbour ) ) + { this.refreshPeripheral(); } } } @Override - public void blockTick() { - if (this.getWorld().isClient) { + public void blockTick() + { + if( this.getWorld().isClient ) + { return; } this.refreshDirection(); - if (this.m_modem.getModemState() - .pollChanged()) { + if( this.m_modem.getModemState() + .pollChanged() ) + { this.updateBlockState(); } - if (!this.m_connectionsFormed) { + if( !this.m_connectionsFormed ) + { this.m_connectionsFormed = true; this.connectionsChanged(); - if (this.m_peripheralAccessAllowed) { - this.m_peripheral.attach(this.world, this.pos, this.modemDirection); + if( this.m_peripheralAccessAllowed ) + { + this.m_peripheral.attach( this.world, this.pos, this.modemDirection ); this.updateConnectedPeripherals(); } } } - private void togglePeripheralAccess() { - if (!this.m_peripheralAccessAllowed) { - this.m_peripheral.attach(this.world, this.getPos(), this.getDirection()); - if (!this.m_peripheral.hasPeripheral()) { + private void togglePeripheralAccess() + { + if( !this.m_peripheralAccessAllowed ) + { + this.m_peripheral.attach( this.world, this.getPos(), this.getDirection() ); + if( !this.m_peripheral.hasPeripheral() ) + { return; } this.m_peripheralAccessAllowed = true; - this.m_node.updatePeripherals(this.m_peripheral.toMap()); - } else { + this.m_node.updatePeripherals( this.m_peripheral.toMap() ); + } + else + { this.m_peripheral.detach(); this.m_peripheralAccessAllowed = false; - this.m_node.updatePeripherals(Collections.emptyMap()); + this.m_node.updatePeripherals( Collections.emptyMap() ); } this.updateBlockState(); } @Nullable - private Direction getMaybeDirection() { + private Direction getMaybeDirection() + { this.refreshDirection(); return this.modemDirection; } - private void refreshDirection() { - if (this.hasModemDirection) { + private void refreshDirection() + { + if( this.hasModemDirection ) + { return; } this.hasModemDirection = true; - this.modemDirection = this.getCachedState().get(BlockCable.MODEM) - .getFacing(); + this.modemDirection = this.getCachedState().get( BlockCable.MODEM ) + .getFacing(); } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); - this.m_peripheralAccessAllowed = nbt.getBoolean(NBT_PERIPHERAL_ENABLED); - this.m_peripheral.read(nbt, ""); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); + this.m_peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); + this.m_peripheral.read( nbt, "" ); } @Nonnull @Override - public CompoundTag toTag(CompoundTag nbt) { - nbt.putBoolean(NBT_PERIPHERAL_ENABLED, this.m_peripheralAccessAllowed); - this.m_peripheral.write(nbt, ""); - return super.toTag(nbt); + public CompoundTag toTag( CompoundTag nbt ) + { + nbt.putBoolean( NBT_PERIPHERAL_ENABLED, this.m_peripheralAccessAllowed ); + this.m_peripheral.write( nbt, "" ); + return super.toTag( nbt ); } @Override - public void markRemoved() { + public void markRemoved() + { super.markRemoved(); this.onRemove(); } @Override - public void cancelRemoval() { + public void cancelRemoval() + { super.cancelRemoval(); - TickScheduler.schedule(this); + TickScheduler.schedule( this ); } @Override - public void resetBlock() { + public void resetBlock() + { super.resetBlock(); this.hasModemDirection = false; - if (!this.world.isClient) { + if( !this.world.isClient ) + { this.world.getBlockTickScheduler() - .schedule(this.pos, - this.getCachedState().getBlock(), 0); + .schedule( this.pos, + this.getCachedState().getBlock(), 0 ); } } - public IWiredElement getElement(Direction facing) { - return BlockCable.canConnectIn(this.getCachedState(), facing) ? this.m_cable : null; + public IWiredElement getElement( Direction facing ) + { + return BlockCable.canConnectIn( this.getCachedState(), facing ) ? this.m_cable : null; } @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { + public IPeripheral getPeripheral( Direction side ) + { return !this.m_destroyed && this.hasModem() && side == this.getDirection() ? this.m_modem : null; } - private class CableElement extends WiredModemElement { + private class CableElement extends WiredModemElement + { @Nonnull @Override - public World getWorld() { + public World getWorld() + { return TileCable.this.getWorld(); } @Nonnull @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { BlockPos pos = TileCable.this.getPos(); - return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); } @Override - protected void attachPeripheral(String name, IPeripheral peripheral) { - TileCable.this.m_modem.attachPeripheral(name, peripheral); + protected void attachPeripheral( String name, IPeripheral peripheral ) + { + TileCable.this.m_modem.attachPeripheral( name, peripheral ); } @Override - protected void detachPeripheral(String name) { - TileCable.this.m_modem.detachPeripheral(name); + protected void detachPeripheral( String name ) + { + TileCable.this.m_modem.detachPeripheral( name ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java index d258877ca..886585ebc 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java @@ -6,21 +6,6 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.MODEM_ON; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.PERIPHERAL_ON; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nonnull; - import com.google.common.base.Objects; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.network.wired.IWiredElement; @@ -32,7 +17,6 @@ import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.peripheral.modem.ModemState; import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.TickScheduler; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; @@ -47,27 +31,39 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { +import javax.annotation.Nonnull; +import java.util.*; + +import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.MODEM_ON; +import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.PERIPHERAL_ON; + +public class TileWiredModemFull extends TileGeneric implements IPeripheralTile +{ private static final String NBT_PERIPHERAL_ENABLED = "PeripheralAccess"; private final WiredModemPeripheral[] modems = new WiredModemPeripheral[6]; private final WiredModemLocalPeripheral[] m_peripherals = new WiredModemLocalPeripheral[6]; - private final ModemState m_modemState = new ModemState(() -> TickScheduler.schedule(this)); - private final WiredModemElement m_element = new FullElement(this); + private final ModemState m_modemState = new ModemState( () -> TickScheduler.schedule( this ) ); + private final WiredModemElement m_element = new FullElement( this ); private final IWiredNode m_node = this.m_element.getNode(); private boolean m_peripheralAccessAllowed = false; private boolean m_destroyed = false; private boolean m_connectionsFormed = false; - public TileWiredModemFull(BlockEntityType type) { - super(type); - for (int i = 0; i < this.m_peripherals.length; i++) { - Direction facing = Direction.byId(i); + + public TileWiredModemFull( BlockEntityType type ) + { + super( type ); + for( int i = 0; i < this.m_peripherals.length; i++ ) + { + Direction facing = Direction.byId( i ); this.m_peripherals[i] = new WiredModemLocalPeripheral(); } } @Override - public void destroy() { - if (!this.m_destroyed) { + public void destroy() + { + if( !this.m_destroyed ) + { this.m_destroyed = true; this.doRemove(); } @@ -81,8 +77,10 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { doRemove(); } - private void doRemove() { - if (this.world == null || !this.world.isClient) { + private void doRemove() + { + if( this.world == null || !this.world.isClient ) + { this.m_node.remove(); this.m_connectionsFormed = false; } @@ -90,8 +88,10 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - if (this.getWorld().isClient) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + if( this.getWorld().isClient ) + { return ActionResult.SUCCESS; } @@ -100,283 +100,347 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { this.togglePeripheralAccess(); Set periphNames = this.getConnectedPeripheralNames(); - if (!Objects.equal(periphNames, oldPeriphNames)) { - sendPeripheralChanges(player, "chat.computercraft.wired_modem.peripheral_disconnected", oldPeriphNames); - sendPeripheralChanges(player, "chat.computercraft.wired_modem.peripheral_connected", periphNames); + if( !Objects.equal( periphNames, oldPeriphNames ) ) + { + sendPeripheralChanges( player, "chat.computercraft.wired_modem.peripheral_disconnected", oldPeriphNames ); + sendPeripheralChanges( player, "chat.computercraft.wired_modem.peripheral_connected", periphNames ); } return ActionResult.SUCCESS; } @Override - public void onNeighbourChange(@Nonnull BlockPos neighbour) { - this.onNeighbourTileEntityChange(neighbour); + public void onNeighbourChange( @Nonnull BlockPos neighbour ) + { + this.onNeighbourTileEntityChange( neighbour ); } @Override - public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) { - if (!this.world.isClient && this.m_peripheralAccessAllowed) { - for (Direction facing : DirectionUtil.FACINGS) { - if (this.getPos().offset(facing) - .equals(neighbour)) { - this.refreshPeripheral(facing); + public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) + { + if( !this.world.isClient && this.m_peripheralAccessAllowed ) + { + for( Direction facing : DirectionUtil.FACINGS ) + { + if( this.getPos().offset( facing ) + .equals( neighbour ) ) + { + this.refreshPeripheral( facing ); } } } } @Override - public void blockTick() { - if (this.getWorld().isClient) { + public void blockTick() + { + if( this.getWorld().isClient ) + { return; } - if (this.m_modemState.pollChanged()) { + if( this.m_modemState.pollChanged() ) + { this.updateBlockState(); } - if (!this.m_connectionsFormed) { + if( !this.m_connectionsFormed ) + { this.m_connectionsFormed = true; this.connectionsChanged(); - if (this.m_peripheralAccessAllowed) { - for (Direction facing : DirectionUtil.FACINGS) { - this.m_peripherals[facing.ordinal()].attach(this.world, this.getPos(), facing); + if( this.m_peripheralAccessAllowed ) + { + for( Direction facing : DirectionUtil.FACINGS ) + { + this.m_peripherals[facing.ordinal()].attach( this.world, this.getPos(), facing ); } this.updateConnectedPeripherals(); } } } - private void connectionsChanged() { - if (this.getWorld().isClient) { + private void connectionsChanged() + { + if( this.getWorld().isClient ) + { return; } World world = this.getWorld(); BlockPos current = this.getPos(); - for (Direction facing : DirectionUtil.FACINGS) { - BlockPos offset = current.offset(facing); - if (!world.isChunkLoaded(offset)) { + for( Direction facing : DirectionUtil.FACINGS ) + { + BlockPos offset = current.offset( facing ); + if( !world.isChunkLoaded( offset ) ) + { continue; } - IWiredElement element = ComputerCraftAPI.getWiredElementAt(world, offset, facing.getOpposite()); - if (element == null) { + IWiredElement element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); + if( element == null ) + { continue; } - this.m_node.connectTo(element.getNode()); + this.m_node.connectTo( element.getNode() ); } } - private void refreshPeripheral(@Nonnull Direction facing) { + private void refreshPeripheral( @Nonnull Direction facing ) + { WiredModemLocalPeripheral peripheral = this.m_peripherals[facing.ordinal()]; - if (this.world != null && !this.isRemoved() && peripheral.attach(this.world, this.getPos(), facing)) { + if( this.world != null && !this.isRemoved() && peripheral.attach( this.world, this.getPos(), facing ) ) + { this.updateConnectedPeripherals(); } } - private void updateConnectedPeripherals() { + private void updateConnectedPeripherals() + { Map peripherals = this.getConnectedPeripherals(); - if (peripherals.isEmpty()) { + if( peripherals.isEmpty() ) + { // If there are no peripherals then disable access and update the display state. this.m_peripheralAccessAllowed = false; this.updateBlockState(); } - this.m_node.updatePeripherals(peripherals); + this.m_node.updatePeripherals( peripherals ); } - private Map getConnectedPeripherals() { - if (!this.m_peripheralAccessAllowed) { + private Map getConnectedPeripherals() + { + if( !this.m_peripheralAccessAllowed ) + { return Collections.emptyMap(); } - Map peripherals = new HashMap<>(6); - for (WiredModemLocalPeripheral peripheral : this.m_peripherals) { - peripheral.extendMap(peripherals); + Map peripherals = new HashMap<>( 6 ); + for( WiredModemLocalPeripheral peripheral : this.m_peripherals ) + { + peripheral.extendMap( peripherals ); } return peripherals; } - private void updateBlockState() { + private void updateBlockState() + { BlockState state = this.getCachedState(); boolean modemOn = this.m_modemState.isOpen(), peripheralOn = this.m_peripheralAccessAllowed; - if (state.get(MODEM_ON) == modemOn && state.get(PERIPHERAL_ON) == peripheralOn) { + if( state.get( MODEM_ON ) == modemOn && state.get( PERIPHERAL_ON ) == peripheralOn ) + { return; } - this.getWorld().setBlockState(this.getPos(), - state.with(MODEM_ON, modemOn) - .with(PERIPHERAL_ON, peripheralOn)); + this.getWorld().setBlockState( this.getPos(), + state.with( MODEM_ON, modemOn ) + .with( PERIPHERAL_ON, peripheralOn ) ); } - private Set getConnectedPeripheralNames() { - if (!this.m_peripheralAccessAllowed) { + private Set getConnectedPeripheralNames() + { + if( !this.m_peripheralAccessAllowed ) + { return Collections.emptySet(); } - Set peripherals = new HashSet<>(6); - for (WiredModemLocalPeripheral peripheral : this.m_peripherals) { + Set peripherals = new HashSet<>( 6 ); + for( WiredModemLocalPeripheral peripheral : this.m_peripherals ) + { String name = peripheral.getConnectedName(); - if (name != null) { - peripherals.add(name); + if( name != null ) + { + peripherals.add( name ); } } return peripherals; } - private void togglePeripheralAccess() { - if (!this.m_peripheralAccessAllowed) { + private void togglePeripheralAccess() + { + if( !this.m_peripheralAccessAllowed ) + { boolean hasAny = false; - for (Direction facing : DirectionUtil.FACINGS) { + for( Direction facing : DirectionUtil.FACINGS ) + { WiredModemLocalPeripheral peripheral = this.m_peripherals[facing.ordinal()]; - peripheral.attach(this.world, this.getPos(), facing); + peripheral.attach( this.world, this.getPos(), facing ); hasAny |= peripheral.hasPeripheral(); } - if (!hasAny) { + if( !hasAny ) + { return; } this.m_peripheralAccessAllowed = true; - this.m_node.updatePeripherals(this.getConnectedPeripherals()); - } else { + this.m_node.updatePeripherals( this.getConnectedPeripherals() ); + } + else + { this.m_peripheralAccessAllowed = false; - for (WiredModemLocalPeripheral peripheral : this.m_peripherals) { + for( WiredModemLocalPeripheral peripheral : this.m_peripherals ) + { peripheral.detach(); } - this.m_node.updatePeripherals(Collections.emptyMap()); + this.m_node.updatePeripherals( Collections.emptyMap() ); } this.updateBlockState(); } - private static void sendPeripheralChanges(PlayerEntity player, String kind, Collection peripherals) { - if (peripherals.isEmpty()) { + private static void sendPeripheralChanges( PlayerEntity player, String kind, Collection peripherals ) + { + if( peripherals.isEmpty() ) + { return; } - List names = new ArrayList<>(peripherals); - names.sort(Comparator.naturalOrder()); + List names = new ArrayList<>( peripherals ); + names.sort( Comparator.naturalOrder() ); - LiteralText base = new LiteralText(""); - for (int i = 0; i < names.size(); i++) { - if (i > 0) { - base.append(", "); + LiteralText base = new LiteralText( "" ); + for( int i = 0; i < names.size(); i++ ) + { + if( i > 0 ) + { + base.append( ", " ); } - base.append(ChatHelpers.copy(names.get(i))); + base.append( ChatHelpers.copy( names.get( i ) ) ); } - player.sendMessage(new TranslatableText(kind, base), false); + player.sendMessage( new TranslatableText( kind, base ), false ); } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); - this.m_peripheralAccessAllowed = nbt.getBoolean(NBT_PERIPHERAL_ENABLED); - for (int i = 0; i < this.m_peripherals.length; i++) { - this.m_peripherals[i].read(nbt, Integer.toString(i)); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); + this.m_peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); + for( int i = 0; i < this.m_peripherals.length; i++ ) + { + this.m_peripherals[i].read( nbt, Integer.toString( i ) ); } } @Nonnull @Override - public CompoundTag toTag(CompoundTag nbt) { - nbt.putBoolean(NBT_PERIPHERAL_ENABLED, this.m_peripheralAccessAllowed); - for (int i = 0; i < this.m_peripherals.length; i++) { - this.m_peripherals[i].write(nbt, Integer.toString(i)); + public CompoundTag toTag( CompoundTag nbt ) + { + nbt.putBoolean( NBT_PERIPHERAL_ENABLED, this.m_peripheralAccessAllowed ); + for( int i = 0; i < this.m_peripherals.length; i++ ) + { + this.m_peripherals[i].write( nbt, Integer.toString( i ) ); } - return super.toTag(nbt); + return super.toTag( nbt ); } @Override - public void markRemoved() { + public void markRemoved() + { super.markRemoved(); this.doRemove(); } @Override - public void cancelRemoval() { + public void cancelRemoval() + { super.cancelRemoval(); - TickScheduler.schedule(this); + TickScheduler.schedule( this ); } - public IWiredElement getElement() { + public IWiredElement getElement() + { return this.m_element; } @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { + public IPeripheral getPeripheral( Direction side ) + { WiredModemPeripheral peripheral = this.modems[side.ordinal()]; - if (peripheral != null) { + if( peripheral != null ) + { return peripheral; } WiredModemLocalPeripheral localPeripheral = this.m_peripherals[side.ordinal()]; - return this.modems[side.ordinal()] = new WiredModemPeripheral(this.m_modemState, this.m_element) { + return this.modems[side.ordinal()] = new WiredModemPeripheral( this.m_modemState, this.m_element ) + { @Nonnull @Override - protected WiredModemLocalPeripheral getLocalPeripheral() { + protected WiredModemLocalPeripheral getLocalPeripheral() + { return localPeripheral; } @Nonnull @Override - public Vec3d getPosition() { - BlockPos pos = TileWiredModemFull.this.getPos().offset(side); - return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + public Vec3d getPosition() + { + BlockPos pos = TileWiredModemFull.this.getPos().offset( side ); + return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); } @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return TileWiredModemFull.this; } }; } - private static final class FullElement extends WiredModemElement { + private static final class FullElement extends WiredModemElement + { private final TileWiredModemFull m_entity; - private FullElement(TileWiredModemFull entity) { + private FullElement( TileWiredModemFull entity ) + { this.m_entity = entity; } @Override - protected void detachPeripheral(String name) { - for (int i = 0; i < 6; i++) { + protected void detachPeripheral( String name ) + { + for( int i = 0; i < 6; i++ ) + { WiredModemPeripheral modem = this.m_entity.modems[i]; - if (modem != null) { - modem.detachPeripheral(name); + if( modem != null ) + { + modem.detachPeripheral( name ); } } } @Override - protected void attachPeripheral(String name, IPeripheral peripheral) { - for (int i = 0; i < 6; i++) { + protected void attachPeripheral( String name, IPeripheral peripheral ) + { + for( int i = 0; i < 6; i++ ) + { WiredModemPeripheral modem = this.m_entity.modems[i]; - if (modem != null) { - modem.attachPeripheral(name, peripheral); + if( modem != null ) + { + modem.attachPeripheral( name, peripheral ); } } } @Nonnull @Override - public World getWorld() { + public World getWorld() + { return this.m_entity.getWorld(); } @Nonnull @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { BlockPos pos = this.m_entity.getPos(); - return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemElement.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemElement.java index dae2cdcd1..3eb19e6d6 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemElement.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemElement.java @@ -6,57 +6,64 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.network.wired.IWiredElement; import dan200.computercraft.api.network.wired.IWiredNetworkChange; import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.wired.WiredNode; -public abstract class WiredModemElement implements IWiredElement { - private final IWiredNode node = new WiredNode(this); +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; + +public abstract class WiredModemElement implements IWiredElement +{ + private final IWiredNode node = new WiredNode( this ); private final Map remotePeripherals = new HashMap<>(); @Nonnull @Override - public IWiredNode getNode() { + public IWiredNode getNode() + { return this.node; } @Nonnull @Override - public String getSenderID() { + public String getSenderID() + { return "modem"; } @Override - public void networkChanged(@Nonnull IWiredNetworkChange change) { - synchronized (this.remotePeripherals) { + public void networkChanged( @Nonnull IWiredNetworkChange change ) + { + synchronized( this.remotePeripherals ) + { this.remotePeripherals.keySet() - .removeAll(change.peripheralsRemoved() - .keySet()); - for (String name : change.peripheralsRemoved() - .keySet()) { - this.detachPeripheral(name); + .removeAll( change.peripheralsRemoved() + .keySet() ); + for( String name : change.peripheralsRemoved() + .keySet() ) + { + this.detachPeripheral( name ); } - for (Map.Entry peripheral : change.peripheralsAdded() - .entrySet()) { - this.attachPeripheral(peripheral.getKey(), peripheral.getValue()); + for( Map.Entry peripheral : change.peripheralsAdded() + .entrySet() ) + { + this.attachPeripheral( peripheral.getKey(), peripheral.getValue() ); } - this.remotePeripherals.putAll(change.peripheralsAdded()); + this.remotePeripherals.putAll( change.peripheralsAdded() ); } } - protected abstract void detachPeripheral(String name); + protected abstract void detachPeripheral( String name ); - protected abstract void attachPeripheral(String name, IPeripheral peripheral); + protected abstract void attachPeripheral( String name, IPeripheral peripheral ); - public Map getRemotePeripherals() { + public Map getRemotePeripherals() + { return this.remotePeripherals; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java index 2ef294fcb..271a10ed5 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java @@ -6,30 +6,29 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import java.util.Collections; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.Peripherals; import dan200.computercraft.shared.util.IDAssigner; import dan200.computercraft.shared.util.NBTUtil; - import net.minecraft.block.Block; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.Map; + /** * Represents a local peripheral exposed on the wired network. * * This is responsible for getting the peripheral in world, tracking id and type and determining whether it has changed. */ -public final class WiredModemLocalPeripheral { +public final class WiredModemLocalPeripheral +{ private static final String NBT_PERIPHERAL_TYPE = "PeripheralType"; private static final String NBT_PERIPHERAL_ID = "PeripheralId"; @@ -41,44 +40,53 @@ public final class WiredModemLocalPeripheral { /** * Attach a new peripheral from the world. * - * @param world The world to search in - * @param origin The position to search from + * @param world The world to search in + * @param origin The position to search from * @param direction The direction so search in * @return Whether the peripheral changed. */ - public boolean attach(@Nonnull World world, @Nonnull BlockPos origin, @Nonnull Direction direction) { + public boolean attach( @Nonnull World world, @Nonnull BlockPos origin, @Nonnull Direction direction ) + { IPeripheral oldPeripheral = this.peripheral; - IPeripheral peripheral = this.peripheral = this.getPeripheralFrom(world, origin, direction); + IPeripheral peripheral = this.peripheral = this.getPeripheralFrom( world, origin, direction ); - if (peripheral == null) { + if( peripheral == null ) + { return oldPeripheral != null; - } else { + } + else + { String type = peripheral.getType(); int id = this.id; - if (id > 0 && this.type == null) { + if( id > 0 && this.type == null ) + { // If we had an ID but no type, then just set the type. this.type = type; - } else if (id < 0 || !type.equals(this.type)) { + } + else if( id < 0 || !type.equals( this.type ) ) + { this.type = type; - this.id = IDAssigner.getNextId("peripheral." + type); + this.id = IDAssigner.getNextId( "peripheral." + type ); } - return oldPeripheral == null || !oldPeripheral.equals(peripheral); + return oldPeripheral == null || !oldPeripheral.equals( peripheral ); } } @Nullable - private IPeripheral getPeripheralFrom(World world, BlockPos pos, Direction direction) { - BlockPos offset = pos.offset(direction); + private IPeripheral getPeripheralFrom( World world, BlockPos pos, Direction direction ) + { + BlockPos offset = pos.offset( direction ); - Block block = world.getBlockState(offset) - .getBlock(); - if (block == ComputerCraftRegistry.ModBlocks.WIRED_MODEM_FULL || block == ComputerCraftRegistry.ModBlocks.CABLE) { + Block block = world.getBlockState( offset ) + .getBlock(); + if( block == ComputerCraftRegistry.ModBlocks.WIRED_MODEM_FULL || block == ComputerCraftRegistry.ModBlocks.CABLE ) + { return null; } - IPeripheral peripheral = Peripherals.getPeripheral(world, offset, direction.getOpposite()); + IPeripheral peripheral = Peripherals.getPeripheral( world, offset, direction.getOpposite() ); return peripheral instanceof WiredModemPeripheral ? null : peripheral; } @@ -87,8 +95,10 @@ public final class WiredModemLocalPeripheral { * * @return Whether the peripheral changed */ - public boolean detach() { - if (this.peripheral == null) { + public boolean detach() + { + if( this.peripheral == null ) + { return false; } this.peripheral = null; @@ -96,41 +106,51 @@ public final class WiredModemLocalPeripheral { } @Nullable - public String getConnectedName() { + public String getConnectedName() + { return this.peripheral != null ? this.type + "_" + this.id : null; } @Nullable - public IPeripheral getPeripheral() { + public IPeripheral getPeripheral() + { return this.peripheral; } - public boolean hasPeripheral() { + public boolean hasPeripheral() + { return this.peripheral != null; } - public void extendMap(@Nonnull Map peripherals) { - if (this.peripheral != null) { - peripherals.put(this.type + "_" + this.id, this.peripheral); + public void extendMap( @Nonnull Map peripherals ) + { + if( this.peripheral != null ) + { + peripherals.put( this.type + "_" + this.id, this.peripheral ); } } - public Map toMap() { - return this.peripheral == null ? Collections.emptyMap() : Collections.singletonMap(this.type + "_" + this.id, this.peripheral); + public Map toMap() + { + return this.peripheral == null ? Collections.emptyMap() : Collections.singletonMap( this.type + "_" + this.id, this.peripheral ); } - public void write(@Nonnull CompoundTag tag, @Nonnull String suffix) { - if (this.id >= 0) { - tag.putInt(NBT_PERIPHERAL_ID + suffix, this.id); + public void write( @Nonnull CompoundTag tag, @Nonnull String suffix ) + { + if( this.id >= 0 ) + { + tag.putInt( NBT_PERIPHERAL_ID + suffix, this.id ); } - if (this.type != null) { - tag.putString(NBT_PERIPHERAL_TYPE + suffix, this.type); + if( this.type != null ) + { + tag.putString( NBT_PERIPHERAL_TYPE + suffix, this.type ); } } - public void read(@Nonnull CompoundTag tag, @Nonnull String suffix) { - this.id = tag.contains(NBT_PERIPHERAL_ID + suffix, NBTUtil.TAG_ANY_NUMERIC) ? tag.getInt(NBT_PERIPHERAL_ID + suffix) : -1; + public void read( @Nonnull CompoundTag tag, @Nonnull String suffix ) + { + this.id = tag.contains( NBT_PERIPHERAL_ID + suffix, NBTUtil.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_PERIPHERAL_ID + suffix ) : -1; - this.type = tag.contains(NBT_PERIPHERAL_TYPE + suffix, NBTUtil.TAG_STRING) ? tag.getString(NBT_PERIPHERAL_TYPE + suffix) : null; + this.type = tag.contains( NBT_PERIPHERAL_TYPE + suffix, NBTUtil.TAG_STRING ) ? tag.getString( NBT_PERIPHERAL_TYPE + suffix ) : null; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java index fb6b08b77..147e956dd 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java @@ -6,24 +6,10 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.collect.ImmutableMap; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.lua.*; import dan200.computercraft.api.network.IPacketNetwork; import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.network.wired.IWiredSender; @@ -34,86 +20,111 @@ import dan200.computercraft.core.apis.PeripheralAPI; import dan200.computercraft.core.asm.PeripheralMethod; import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; import dan200.computercraft.shared.peripheral.modem.ModemState; - import net.minecraft.world.World; -public abstract class WiredModemPeripheral extends ModemPeripheral implements IWiredSender { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public abstract class WiredModemPeripheral extends ModemPeripheral implements IWiredSender +{ private final WiredModemElement modem; - private final Map> peripheralWrappers = new HashMap<>(1); + private final Map> peripheralWrappers = new HashMap<>( 1 ); - public WiredModemPeripheral(ModemState state, WiredModemElement modem) { - super(state); + public WiredModemPeripheral( ModemState state, WiredModemElement modem ) + { + super( state ); this.modem = modem; } @Override - public double getRange() { + public double getRange() + { return 256.0; } //region IPacketSender implementation @Override - public boolean isInterdimensional() { + public boolean isInterdimensional() + { return false; } @Override - protected IPacketNetwork getNetwork() { + protected IPacketNetwork getNetwork() + { return this.modem.getNode(); } @Override - public void attach(@Nonnull IComputerAccess computer) { - super.attach(computer); + public void attach( @Nonnull IComputerAccess computer ) + { + super.attach( computer ); ConcurrentMap wrappers; - synchronized (this.peripheralWrappers) { - wrappers = this.peripheralWrappers.get(computer); - if (wrappers == null) { - this.peripheralWrappers.put(computer, wrappers = new ConcurrentHashMap<>()); + synchronized( this.peripheralWrappers ) + { + wrappers = this.peripheralWrappers.get( computer ); + if( wrappers == null ) + { + this.peripheralWrappers.put( computer, wrappers = new ConcurrentHashMap<>() ); } } - synchronized (this.modem.getRemotePeripherals()) { - for (Map.Entry entry : this.modem.getRemotePeripherals() - .entrySet()) { - this.attachPeripheralImpl(computer, wrappers, entry.getKey(), entry.getValue()); + synchronized( this.modem.getRemotePeripherals() ) + { + for( Map.Entry entry : this.modem.getRemotePeripherals() + .entrySet() ) + { + this.attachPeripheralImpl( computer, wrappers, entry.getKey(), entry.getValue() ); } } } @Override - public void detach(@Nonnull IComputerAccess computer) { + public void detach( @Nonnull IComputerAccess computer ) + { Map wrappers; - synchronized (this.peripheralWrappers) { - wrappers = this.peripheralWrappers.remove(computer); + synchronized( this.peripheralWrappers ) + { + wrappers = this.peripheralWrappers.remove( computer ); } - if (wrappers != null) { - for (RemotePeripheralWrapper wrapper : wrappers.values()) { + if( wrappers != null ) + { + for( RemotePeripheralWrapper wrapper : wrappers.values() ) + { wrapper.detach(); } wrappers.clear(); } - super.detach(computer); + super.detach( computer ); } //endregion //region Peripheral methods - private void attachPeripheralImpl(IComputerAccess computer, ConcurrentMap peripherals, String periphName, - IPeripheral peripheral) { - if (!peripherals.containsKey(periphName) && !periphName.equals(this.getLocalPeripheral().getConnectedName())) { - RemotePeripheralWrapper wrapper = new RemotePeripheralWrapper(this.modem, peripheral, computer, periphName); - peripherals.put(periphName, wrapper); + private void attachPeripheralImpl( IComputerAccess computer, ConcurrentMap peripherals, String periphName, + IPeripheral peripheral ) + { + if( !peripherals.containsKey( periphName ) && !periphName.equals( this.getLocalPeripheral().getConnectedName() ) ) + { + RemotePeripheralWrapper wrapper = new RemotePeripheralWrapper( this.modem, peripheral, computer, periphName ); + peripherals.put( periphName, wrapper ); wrapper.attach(); } } @Nonnull @Override - public World getWorld() { + public World getWorld() + { return this.modem.getWorld(); } @@ -129,13 +140,16 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW * @return Remote peripheral names on the network. */ @LuaFunction - public final Collection getNamesRemote(IComputerAccess computer) { - return this.getWrappers(computer).keySet(); + public final Collection getNamesRemote( IComputerAccess computer ) + { + return this.getWrappers( computer ).keySet(); } - private ConcurrentMap getWrappers(IComputerAccess computer) { - synchronized (this.peripheralWrappers) { - return this.peripheralWrappers.get(computer); + private ConcurrentMap getWrappers( IComputerAccess computer ) + { + synchronized( this.peripheralWrappers ) + { + return this.peripheralWrappers.get( computer ); } } @@ -146,18 +160,20 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW * returns false before calling it. * * @param computer The calling computer. - * @param name The peripheral's name. + * @param name The peripheral's name. * @return boolean If a peripheral is present with the given name. * @see PeripheralAPI#isPresent */ @LuaFunction - public final boolean isPresentRemote(IComputerAccess computer, String name) { - return this.getWrapper(computer, name) != null; + public final boolean isPresentRemote( IComputerAccess computer, String name ) + { + return this.getWrapper( computer, name ) != null; } - private RemotePeripheralWrapper getWrapper(IComputerAccess computer, String remoteName) { - ConcurrentMap wrappers = this.getWrappers(computer); - return wrappers == null ? null : wrappers.get(remoteName); + private RemotePeripheralWrapper getWrapper( IComputerAccess computer, String remoteName ) + { + ConcurrentMap wrappers = this.getWrappers( computer ); + return wrappers == null ? null : wrappers.get( remoteName ); } /** @@ -167,15 +183,16 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW * returns false before calling it. * * @param computer The calling computer. - * @param name The peripheral's name. + * @param name The peripheral's name. * @return The peripheral's name. * @cc.treturn string|nil The peripheral's type, or {@code nil} if it is not present. * @see PeripheralAPI#getType */ @LuaFunction - public final Object[] getTypeRemote(IComputerAccess computer, String name) { - RemotePeripheralWrapper wrapper = this.getWrapper(computer, name); - return wrapper != null ? new Object[] {wrapper.getType()} : null; + public final Object[] getTypeRemote( IComputerAccess computer, String name ) + { + RemotePeripheralWrapper wrapper = this.getWrapper( computer, name ); + return wrapper != null ? new Object[] { wrapper.getType() } : null; } /** @@ -185,19 +202,21 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW * returns false before calling it. * * @param computer The calling computer. - * @param name The peripheral's name. + * @param name The peripheral's name. * @return A list of methods provided by this peripheral, or {@code nil} if it is not present. * @cc.treturn { string... }|nil A list of methods provided by this peripheral, or {@code nil} if it is not present. * @see PeripheralAPI#getMethods */ @LuaFunction - public final Object[] getMethodsRemote(IComputerAccess computer, String name) { - RemotePeripheralWrapper wrapper = this.getWrapper(computer, name); - if (wrapper == null) { + public final Object[] getMethodsRemote( IComputerAccess computer, String name ) + { + RemotePeripheralWrapper wrapper = this.getWrapper( computer, name ); + if( wrapper == null ) + { return null; } - return new Object[] {wrapper.getMethodNames()}; + return new Object[] { wrapper.getMethodNames() }; } /** @@ -206,8 +225,8 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW *
    Important: This function only appears on wired modems. Check {@link #isWireless} * returns false before calling it.
    * - * @param computer The calling computer. - * @param context The Lua context we're executing in. + * @param computer The calling computer. + * @param context The Lua context we're executing in. * @param arguments Arguments to this computer. * @return The peripheral's result. * @throws LuaException (hidden) If the method throws an error. @@ -218,15 +237,17 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW * @see PeripheralAPI#call */ @LuaFunction - public final MethodResult callRemote(IComputerAccess computer, ILuaContext context, IArguments arguments) throws LuaException { - String remoteName = arguments.getString(0); - String methodName = arguments.getString(1); - RemotePeripheralWrapper wrapper = this.getWrapper(computer, remoteName); - if (wrapper == null) { - throw new LuaException("No peripheral: " + remoteName); + public final MethodResult callRemote( IComputerAccess computer, ILuaContext context, IArguments arguments ) throws LuaException + { + String remoteName = arguments.getString( 0 ); + String methodName = arguments.getString( 1 ); + RemotePeripheralWrapper wrapper = this.getWrapper( computer, remoteName ); + if( wrapper == null ) + { + throw new LuaException( "No peripheral: " + remoteName ); } - return wrapper.callMethod(context, methodName, arguments.drop(2)); + return wrapper.callMethod( context, methodName, arguments.drop( 2 ) ); } //endregion @@ -241,17 +262,20 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW * @cc.treturn string|nil The current computer's name on the wired network. */ @LuaFunction - public final Object[] getNameLocal() { + public final Object[] getNameLocal() + { String local = this.getLocalPeripheral().getConnectedName(); - return local == null ? null : new Object[] {local}; + return local == null ? null : new Object[] { local }; } @Nonnull protected abstract WiredModemLocalPeripheral getLocalPeripheral(); @Override - public boolean equals(IPeripheral other) { - if (other instanceof WiredModemPeripheral) { + public boolean equals( IPeripheral other ) + { + if( other instanceof WiredModemPeripheral ) + { WiredModemPeripheral otherModem = (WiredModemPeripheral) other; return otherModem.modem == this.modem; } @@ -260,23 +284,31 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW @Nonnull @Override - public IWiredNode getNode() { + public IWiredNode getNode() + { return this.modem.getNode(); } - public void attachPeripheral(String name, IPeripheral peripheral) { - synchronized (this.peripheralWrappers) { - for (Map.Entry> entry : this.peripheralWrappers.entrySet()) { - this.attachPeripheralImpl(entry.getKey(), entry.getValue(), name, peripheral); + public void attachPeripheral( String name, IPeripheral peripheral ) + { + synchronized( this.peripheralWrappers ) + { + for( Map.Entry> entry : this.peripheralWrappers.entrySet() ) + { + this.attachPeripheralImpl( entry.getKey(), entry.getValue(), name, peripheral ); } } } - public void detachPeripheral(String name) { - synchronized (this.peripheralWrappers) { - for (ConcurrentMap wrappers : this.peripheralWrappers.values()) { - RemotePeripheralWrapper wrapper = wrappers.remove(name); - if (wrapper != null) { + public void detachPeripheral( String name ) + { + synchronized( this.peripheralWrappers ) + { + for( ConcurrentMap wrappers : this.peripheralWrappers.values() ) + { + RemotePeripheralWrapper wrapper = wrappers.remove( name ); + if( wrapper != null ) + { wrapper.detach(); } } @@ -284,7 +316,8 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW } } - private static class RemotePeripheralWrapper implements IComputerAccess { + private static class RemotePeripheralWrapper implements IComputerAccess + { private final WiredModemElement element; private final IPeripheral peripheral; private final IComputerAccess computer; @@ -293,105 +326,125 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW private final String type; private final Map methodMap; - RemotePeripheralWrapper(WiredModemElement element, IPeripheral peripheral, IComputerAccess computer, String name) { + RemotePeripheralWrapper( WiredModemElement element, IPeripheral peripheral, IComputerAccess computer, String name ) + { this.element = element; this.peripheral = peripheral; this.computer = computer; this.name = name; - this.type = Objects.requireNonNull(peripheral.getType(), "Peripheral type cannot be null"); - this.methodMap = PeripheralAPI.getMethods(peripheral); + this.type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); + this.methodMap = PeripheralAPI.getMethods( peripheral ); } - public void attach() { - this.peripheral.attach(this); - this.computer.queueEvent("peripheral", this.getAttachmentName()); + public void attach() + { + this.peripheral.attach( this ); + this.computer.queueEvent( "peripheral", this.getAttachmentName() ); } - public void detach() { - this.peripheral.detach(this); - this.computer.queueEvent("peripheral_detach", this.getAttachmentName()); + public void detach() + { + this.peripheral.detach( this ); + this.computer.queueEvent( "peripheral_detach", this.getAttachmentName() ); } - public String getType() { + public String getType() + { return this.type; } - public Collection getMethodNames() { + public Collection getMethodNames() + { return this.methodMap.keySet(); } - public MethodResult callMethod(ILuaContext context, String methodName, IArguments arguments) throws LuaException { - PeripheralMethod method = this.methodMap.get(methodName); - if (method == null) { - throw new LuaException("No such method " + methodName); + public MethodResult callMethod( ILuaContext context, String methodName, IArguments arguments ) throws LuaException + { + PeripheralMethod method = this.methodMap.get( methodName ); + if( method == null ) + { + throw new LuaException( "No such method " + methodName ); } - return method.apply(this.peripheral, context, this, arguments); + return method.apply( this.peripheral, context, this, arguments ); } // IComputerAccess implementation @Override - public String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) { - return this.computer.mount(desiredLocation, mount, this.name); + public String mount( @Nonnull String desiredLocation, @Nonnull IMount mount ) + { + return this.computer.mount( desiredLocation, mount, this.name ); } @Override - public String mount(@Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName) { - return this.computer.mount(desiredLocation, mount, driveName); + public String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName ) + { + return this.computer.mount( desiredLocation, mount, driveName ); } @Nonnull @Override - public String getAttachmentName() { + public String getAttachmentName() + { return this.name; } @Override - public String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritableMount mount) { - return this.computer.mountWritable(desiredLocation, mount, this.name); + public String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount ) + { + return this.computer.mountWritable( desiredLocation, mount, this.name ); } @Override - public String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName) { - return this.computer.mountWritable(desiredLocation, mount, driveName); + public String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName ) + { + return this.computer.mountWritable( desiredLocation, mount, driveName ); } @Override - public void unmount(String location) { - this.computer.unmount(location); + public void unmount( String location ) + { + this.computer.unmount( location ); } @Override - public int getID() { + public int getID() + { return this.computer.getID(); } @Override - public void queueEvent(@Nonnull String event, Object... arguments) { - this.computer.queueEvent(event, arguments); + public void queueEvent( @Nonnull String event, Object... arguments ) + { + this.computer.queueEvent( event, arguments ); } @Nonnull @Override - public Map getAvailablePeripherals() { - synchronized (this.element.getRemotePeripherals()) { - return ImmutableMap.copyOf(this.element.getRemotePeripherals()); + public Map getAvailablePeripherals() + { + synchronized( this.element.getRemotePeripherals() ) + { + return ImmutableMap.copyOf( this.element.getRemotePeripherals() ); } } @Nullable @Override - public IPeripheral getAvailablePeripheral(@Nonnull String name) { - synchronized (this.element.getRemotePeripherals()) { + public IPeripheral getAvailablePeripheral( @Nonnull String name ) + { + synchronized( this.element.getRemotePeripherals() ) + { return this.element.getRemotePeripherals() - .get(name); + .get( name ); } } @Nonnull @Override - public IWorkMonitor getMainThreadMonitor() { + public IWorkMonitor getMainThreadMonitor() + { return this.computer.getMainThreadMonitor(); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/BlockWirelessModem.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/BlockWirelessModem.java index b2fb5db29..abdf324d5 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/BlockWirelessModem.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/BlockWirelessModem.java @@ -6,17 +6,8 @@ package dan200.computercraft.shared.peripheral.modem.wireless; -import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED; -import static dan200.computercraft.shared.util.WaterloggableHelpers.getWaterloggedFluidState; -import static dan200.computercraft.shared.util.WaterloggableHelpers.getWaterloggedStateForPlacement; -import static dan200.computercraft.shared.util.WaterloggableHelpers.updateWaterloggedPostPlacement; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.common.BlockGeneric; import dan200.computercraft.shared.peripheral.modem.ModemShapes; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.ShapeContext; @@ -35,60 +26,73 @@ import net.minecraft.world.BlockView; import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldView; -public class BlockWirelessModem extends BlockGeneric implements Waterloggable { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import static dan200.computercraft.shared.util.WaterloggableHelpers.*; + +public class BlockWirelessModem extends BlockGeneric implements Waterloggable +{ public static final DirectionProperty FACING = Properties.FACING; - public static final BooleanProperty ON = BooleanProperty.of("on"); + public static final BooleanProperty ON = BooleanProperty.of( "on" ); - public BlockWirelessModem(Settings settings, BlockEntityType type) { - super(settings, type); - this.setDefaultState(this.getStateManager().getDefaultState() - .with(FACING, Direction.NORTH) - .with(ON, false) - .with(WATERLOGGED, false)); + public BlockWirelessModem( Settings settings, BlockEntityType type ) + { + super( settings, type ); + this.setDefaultState( this.getStateManager().getDefaultState() + .with( FACING, Direction.NORTH ) + .with( ON, false ) + .with( WATERLOGGED, false ) ); } @Nonnull @Override @Deprecated - public BlockState getStateForNeighborUpdate(@Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, - @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos) { - updateWaterloggedPostPlacement(state, world, pos); - return side == state.get(FACING) && !state.canPlaceAt(world, pos) ? state.getFluidState() - .getBlockState() : state; + public BlockState getStateForNeighborUpdate( @Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, + @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos ) + { + updateWaterloggedPostPlacement( state, world, pos ); + return side == state.get( FACING ) && !state.canPlaceAt( world, pos ) ? state.getFluidState() + .getBlockState() : state; } @Nonnull @Override @Deprecated - public FluidState getFluidState(@Nonnull BlockState state) { - return getWaterloggedFluidState(state); + public FluidState getFluidState( @Nonnull BlockState state ) + { + return getWaterloggedFluidState( state ); } @Override @Deprecated - public boolean canPlaceAt(BlockState state, @Nonnull WorldView world, BlockPos pos) { - Direction facing = state.get(FACING); - return sideCoversSmallSquare(world, pos.offset(facing), facing.getOpposite()); + public boolean canPlaceAt( BlockState state, @Nonnull WorldView world, BlockPos pos ) + { + Direction facing = state.get( FACING ); + return sideCoversSmallSquare( world, pos.offset( facing ), facing.getOpposite() ); } @Nonnull @Override @Deprecated - public VoxelShape getOutlineShape(BlockState blockState, @Nonnull BlockView blockView, @Nonnull BlockPos blockPos, @Nonnull ShapeContext context) { - return ModemShapes.getBounds(blockState.get(FACING)); + public VoxelShape getOutlineShape( BlockState blockState, @Nonnull BlockView blockView, @Nonnull BlockPos blockPos, @Nonnull ShapeContext context ) + { + return ModemShapes.getBounds( blockState.get( FACING ) ); } @Nullable @Override - public BlockState getPlacementState(ItemPlacementContext placement) { - return this.getDefaultState().with(FACING, - placement.getSide() - .getOpposite()) - .with(WATERLOGGED, getWaterloggedStateForPlacement(placement)); + public BlockState getPlacementState( ItemPlacementContext placement ) + { + return this.getDefaultState().with( FACING, + placement.getSide() + .getOpposite() ) + .with( WATERLOGGED, getWaterloggedStateForPlacement( placement ) ); } @Override - protected void appendProperties(StateManager.Builder builder) { - builder.add(FACING, ON, WATERLOGGED); + protected void appendProperties( StateManager.Builder builder ) + { + builder.add( FACING, ON, WATERLOGGED ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java index 247a3b256..1f761a583 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java @@ -6,15 +6,12 @@ package dan200.computercraft.shared.peripheral.modem.wireless; -import javax.annotation.Nonnull; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheralTile; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; import dan200.computercraft.shared.peripheral.modem.ModemState; import dan200.computercraft.shared.util.TickScheduler; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.util.math.BlockPos; @@ -22,109 +19,131 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class TileWirelessModem extends TileGeneric implements IPeripheralTile { +import javax.annotation.Nonnull; + +public class TileWirelessModem extends TileGeneric implements IPeripheralTile +{ private final boolean advanced; private final ModemPeripheral modem; private boolean hasModemDirection = false; private Direction modemDirection = Direction.DOWN; private boolean destroyed = false; - public TileWirelessModem(BlockEntityType type, boolean advanced) { - super(type); + + public TileWirelessModem( BlockEntityType type, boolean advanced ) + { + super( type ); this.advanced = advanced; - this.modem = new Peripheral(this); + this.modem = new Peripheral( this ); } @Override - public void cancelRemoval() { + public void cancelRemoval() + { super.cancelRemoval(); - TickScheduler.schedule(this); + TickScheduler.schedule( this ); } @Override - public void resetBlock() { + public void resetBlock() + { super.resetBlock(); this.hasModemDirection = false; this.world.getBlockTickScheduler() - .schedule(this.getPos(), - this.getCachedState().getBlock(), 0); + .schedule( this.getPos(), + this.getCachedState().getBlock(), 0 ); } @Override - public void destroy() { - if (!this.destroyed) { + public void destroy() + { + if( !this.destroyed ) + { this.modem.destroy(); this.destroyed = true; } } @Override - public void blockTick() { + public void blockTick() + { Direction currentDirection = this.modemDirection; this.refreshDirection(); // Invalidate the capability if the direction has changed. I'm not 100% happy with this implementation // - ideally we'd do it within refreshDirection or updateContainingBlockInfo, but this seems the _safest_ // place. - if (this.modem.getModemState() - .pollChanged()) { + if( this.modem.getModemState() + .pollChanged() ) + { this.updateBlockState(); } } - private void refreshDirection() { - if (this.hasModemDirection) { + private void refreshDirection() + { + if( this.hasModemDirection ) + { return; } this.hasModemDirection = true; - this.modemDirection = this.getCachedState().get(BlockWirelessModem.FACING); + this.modemDirection = this.getCachedState().get( BlockWirelessModem.FACING ); } - private void updateBlockState() { + private void updateBlockState() + { boolean on = this.modem.getModemState() - .isOpen(); + .isOpen(); BlockState state = this.getCachedState(); - if (state.get(BlockWirelessModem.ON) != on) { - this.getWorld().setBlockState(this.getPos(), state.with(BlockWirelessModem.ON, on)); + if( state.get( BlockWirelessModem.ON ) != on ) + { + this.getWorld().setBlockState( this.getPos(), state.with( BlockWirelessModem.ON, on ) ); } } @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { + public IPeripheral getPeripheral( Direction side ) + { this.refreshDirection(); return side == this.modemDirection ? this.modem : null; } - private static class Peripheral extends WirelessModemPeripheral { + private static class Peripheral extends WirelessModemPeripheral + { private final TileWirelessModem entity; - Peripheral(TileWirelessModem entity) { - super(new ModemState(() -> TickScheduler.schedule(entity)), entity.advanced); + Peripheral( TileWirelessModem entity ) + { + super( new ModemState( () -> TickScheduler.schedule( entity ) ), entity.advanced ); this.entity = entity; } @Nonnull @Override - public World getWorld() { + public World getWorld() + { return this.entity.getWorld(); } @Nonnull @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { BlockPos pos = this.entity.getPos() - .offset(this.entity.modemDirection); - return new Vec3d(pos.getX(), pos.getY(), pos.getZ()); + .offset( this.entity.modemDirection ); + return new Vec3d( pos.getX(), pos.getY(), pos.getZ() ); } @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return this.entity; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return this == other || (other instanceof Peripheral && this.entity == ((Peripheral) other).entity); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java index 514264047..0d69b8e11 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java @@ -10,33 +10,41 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.network.IPacketNetwork; import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; import dan200.computercraft.shared.peripheral.modem.ModemState; - import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public abstract class WirelessModemPeripheral extends ModemPeripheral { +public abstract class WirelessModemPeripheral extends ModemPeripheral +{ private final boolean m_advanced; - public WirelessModemPeripheral(ModemState state, boolean advanced) { - super(state); + public WirelessModemPeripheral( ModemState state, boolean advanced ) + { + super( state ); this.m_advanced = advanced; } @Override - public double getRange() { - if (this.m_advanced) { + public double getRange() + { + if( this.m_advanced ) + { return Integer.MAX_VALUE; - } else { + } + else + { World world = this.getWorld(); - if (world != null) { + if( world != null ) + { Vec3d position = this.getPosition(); double minRange = ComputerCraft.modemRange; double maxRange = ComputerCraft.modemHighAltitudeRange; - if (world.isRaining() && world.isThundering()) { + if( world.isRaining() && world.isThundering() ) + { minRange = ComputerCraft.modemRangeDuringStorm; maxRange = ComputerCraft.modemHighAltitudeRangeDuringStorm; } - if (position.y > 96.0 && maxRange > minRange) { + if( position.y > 96.0 && maxRange > minRange ) + { return minRange + (position.y - 96.0) * ((maxRange - minRange) / ((world.getHeight() - 1) - 96.0)); } return minRange; @@ -46,12 +54,14 @@ public abstract class WirelessModemPeripheral extends ModemPeripheral { } @Override - public boolean isInterdimensional() { + public boolean isInterdimensional() + { return this.m_advanced; } @Override - protected IPacketNetwork getNetwork() { + protected IPacketNetwork getNetwork() + { return WirelessNetwork.getUniversal(); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java index ecb583802..4c0200ffe 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java @@ -6,78 +6,94 @@ package dan200.computercraft.shared.peripheral.modem.wireless; -import java.util.Collections; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.network.IPacketNetwork; import dan200.computercraft.api.network.IPacketReceiver; import dan200.computercraft.api.network.IPacketSender; import dan200.computercraft.api.network.Packet; -public class WirelessNetwork implements IPacketNetwork { - private static WirelessNetwork s_universalNetwork = null; - private final Set m_receivers = Collections.newSetFromMap(new ConcurrentHashMap<>()); +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; - public static WirelessNetwork getUniversal() { - if (s_universalNetwork == null) { +public class WirelessNetwork implements IPacketNetwork +{ + private static WirelessNetwork s_universalNetwork = null; + private final Set m_receivers = Collections.newSetFromMap( new ConcurrentHashMap<>() ); + + public static WirelessNetwork getUniversal() + { + if( s_universalNetwork == null ) + { s_universalNetwork = new WirelessNetwork(); } return s_universalNetwork; } - public static void resetNetworks() { + public static void resetNetworks() + { s_universalNetwork = null; } @Override - public void addReceiver(@Nonnull IPacketReceiver receiver) { - Objects.requireNonNull(receiver, "device cannot be null"); - this.m_receivers.add(receiver); + public void addReceiver( @Nonnull IPacketReceiver receiver ) + { + Objects.requireNonNull( receiver, "device cannot be null" ); + this.m_receivers.add( receiver ); } @Override - public void removeReceiver(@Nonnull IPacketReceiver receiver) { - Objects.requireNonNull(receiver, "device cannot be null"); - this.m_receivers.remove(receiver); + public void removeReceiver( @Nonnull IPacketReceiver receiver ) + { + Objects.requireNonNull( receiver, "device cannot be null" ); + this.m_receivers.remove( receiver ); } @Override - public boolean isWireless() { + public boolean isWireless() + { return true; } @Override - public void transmitSameDimension(@Nonnull Packet packet, double range) { - Objects.requireNonNull(packet, "packet cannot be null"); - for (IPacketReceiver device : this.m_receivers) { - tryTransmit(device, packet, range, false); + public void transmitSameDimension( @Nonnull Packet packet, double range ) + { + Objects.requireNonNull( packet, "packet cannot be null" ); + for( IPacketReceiver device : this.m_receivers ) + { + tryTransmit( device, packet, range, false ); } } @Override - public void transmitInterdimensional(@Nonnull Packet packet) { - Objects.requireNonNull(packet, "packet cannot be null"); - for (IPacketReceiver device : this.m_receivers) { - tryTransmit(device, packet, 0, true); + public void transmitInterdimensional( @Nonnull Packet packet ) + { + Objects.requireNonNull( packet, "packet cannot be null" ); + for( IPacketReceiver device : this.m_receivers ) + { + tryTransmit( device, packet, 0, true ); } } - private static void tryTransmit(IPacketReceiver receiver, Packet packet, double range, boolean interdimensional) { + private static void tryTransmit( IPacketReceiver receiver, Packet packet, double range, boolean interdimensional ) + { IPacketSender sender = packet.getSender(); - if (receiver.getWorld() == sender.getWorld()) { - double receiveRange = Math.max(range, receiver.getRange()); // Ensure range is symmetrical + if( receiver.getWorld() == sender.getWorld() ) + { + double receiveRange = Math.max( range, receiver.getRange() ); // Ensure range is symmetrical double distanceSq = receiver.getPosition() - .squaredDistanceTo(sender.getPosition()); - if (interdimensional || receiver.isInterdimensional() || distanceSq <= receiveRange * receiveRange) { - receiver.receiveSameDimension(packet, Math.sqrt(distanceSq)); + .squaredDistanceTo( sender.getPosition() ); + if( interdimensional || receiver.isInterdimensional() || distanceSq <= receiveRange * receiveRange ) + { + receiver.receiveSameDimension( packet, Math.sqrt( distanceSq ) ); } - } else { - if (interdimensional || receiver.isInterdimensional()) { - receiver.receiveDifferentDimension(packet); + } + else + { + if( interdimensional || receiver.isInterdimensional() ) + { + receiver.receiveDifferentDimension( packet ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java index ebd2799bb..897ea62e0 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java @@ -6,12 +6,8 @@ package dan200.computercraft.shared.peripheral.monitor; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.turtle.FakePlayer; import dan200.computercraft.shared.common.BlockGeneric; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -27,53 +23,66 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class BlockMonitor extends BlockGeneric { - public static final DirectionProperty ORIENTATION = DirectionProperty.of("orientation", Direction.UP, Direction.DOWN, Direction.NORTH); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class BlockMonitor extends BlockGeneric +{ + public static final DirectionProperty ORIENTATION = DirectionProperty.of( "orientation", Direction.UP, Direction.DOWN, Direction.NORTH ); public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - static final EnumProperty STATE = EnumProperty.of("state", MonitorEdgeState.class); + static final EnumProperty STATE = EnumProperty.of( "state", MonitorEdgeState.class ); - public BlockMonitor(Settings settings, BlockEntityType type) { - super(settings, type); + public BlockMonitor( Settings settings, BlockEntityType type ) + { + super( settings, type ); // TODO: Test underwater - do we need isSolid at all? - this.setDefaultState(this.getStateManager().getDefaultState() - .with(ORIENTATION, Direction.NORTH) - .with(FACING, Direction.NORTH) - .with(STATE, MonitorEdgeState.NONE)); + this.setDefaultState( this.getStateManager().getDefaultState() + .with( ORIENTATION, Direction.NORTH ) + .with( FACING, Direction.NORTH ) + .with( STATE, MonitorEdgeState.NONE ) ); } @Override @Nullable - public BlockState getPlacementState(ItemPlacementContext context) { + public BlockState getPlacementState( ItemPlacementContext context ) + { float pitch = context.getPlayer() == null ? 0 : context.getPlayer().pitch; Direction orientation; - if (pitch > 66.5f) { + if( pitch > 66.5f ) + { // If the player is looking down, place it facing upwards orientation = Direction.UP; - } else if (pitch < -66.5f) { + } + else if( pitch < -66.5f ) + { // If they're looking up, place it down. orientation = Direction.DOWN; - } else { + } + else + { orientation = Direction.NORTH; } - return this.getDefaultState().with(FACING, - context.getPlayerFacing() - .getOpposite()) - .with(ORIENTATION, orientation); + return this.getDefaultState().with( FACING, + context.getPlayerFacing() + .getOpposite() ) + .with( ORIENTATION, orientation ); } @Override - public void onPlaced(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState blockState, @Nullable LivingEntity livingEntity, - @Nonnull ItemStack itemStack) { - super.onPlaced(world, pos, blockState, livingEntity, itemStack); + public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState blockState, @Nullable LivingEntity livingEntity, + @Nonnull ItemStack itemStack ) + { + super.onPlaced( world, pos, blockState, livingEntity, itemStack ); - BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileMonitor && !world.isClient) { + BlockEntity entity = world.getBlockEntity( pos ); + if( entity instanceof TileMonitor && !world.isClient ) + { TileMonitor monitor = (TileMonitor) entity; // Defer the block update if we're being placed by another TE. See #691 - if ( livingEntity == null || livingEntity instanceof FakePlayer ) + if( livingEntity == null || livingEntity instanceof FakePlayer ) { monitor.updateNeighborsDeferred(); return; @@ -84,7 +93,8 @@ public class BlockMonitor extends BlockGeneric { } @Override - protected void appendProperties(StateManager.Builder builder) { - builder.add(ORIENTATION, FACING, STATE); + protected void appendProperties( StateManager.Builder builder ) + { + builder.add( ORIENTATION, FACING, STATE ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java index 7ad6d90c8..d7b682f84 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java @@ -6,27 +6,26 @@ package dan200.computercraft.shared.peripheral.monitor; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.shared.common.ClientTerminal; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gl.VertexBuffer; +import net.minecraft.util.math.BlockPos; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL31; -import net.minecraft.client.gl.VertexBuffer; -import net.minecraft.util.math.BlockPos; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; - -@Environment (EnvType.CLIENT) -public final class ClientMonitor extends ClientTerminal { +@Environment( EnvType.CLIENT ) +public final class ClientMonitor extends ClientTerminal +{ private static final Set allMonitors = new HashSet<>(); private final TileMonitor origin; @@ -38,15 +37,19 @@ public final class ClientMonitor extends ClientTerminal { public int tboTexture; public VertexBuffer buffer; - public ClientMonitor(boolean colour, TileMonitor origin) { - super(colour); + public ClientMonitor( boolean colour, TileMonitor origin ) + { + super( colour ); this.origin = origin; } - @Environment (EnvType.CLIENT) - public static void destroyAll() { - synchronized (allMonitors) { - for (Iterator iterator = allMonitors.iterator(); iterator.hasNext(); ) { + @Environment( EnvType.CLIENT ) + public static void destroyAll() + { + synchronized( allMonitors ) + { + for( Iterator iterator = allMonitors.iterator(); iterator.hasNext(); ) + { ClientMonitor monitor = iterator.next(); monitor.deleteBuffers(); @@ -55,7 +58,8 @@ public final class ClientMonitor extends ClientTerminal { } } - public TileMonitor getOrigin() { + public TileMonitor getOrigin() + { return this.origin; } @@ -65,74 +69,88 @@ public final class ClientMonitor extends ClientTerminal { * @param renderer The renderer to use. This can be fetched from {@link MonitorRenderer#current()}. * @return If a buffer was created. This will return {@code false} if we already have an appropriate buffer, or this mode does not require one. */ - @Environment (EnvType.CLIENT) - public boolean createBuffer(MonitorRenderer renderer) { - switch (renderer) { - case TBO: { - if (this.tboBuffer != 0) { - return false; + @Environment( EnvType.CLIENT ) + public boolean createBuffer( MonitorRenderer renderer ) + { + switch( renderer ) + { + case TBO: + { + if( this.tboBuffer != 0 ) + { + return false; + } + + this.deleteBuffers(); + + this.tboBuffer = GlStateManager.genBuffers(); + GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, this.tboBuffer ); + GL15.glBufferData( GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW ); + this.tboTexture = GlStateManager.genTextures(); + GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, this.tboTexture ); + GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, this.tboBuffer ); + GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 ); + + GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, 0 ); + + this.addMonitor(); + return true; } - this.deleteBuffers(); + case VBO: + if( this.buffer != null ) + { + return false; + } - this.tboBuffer = GlStateManager.genBuffers(); - GlStateManager.bindBuffers(GL31.GL_TEXTURE_BUFFER, this.tboBuffer); - GL15.glBufferData(GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW); - this.tboTexture = GlStateManager.genTextures(); - GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, this.tboTexture); - GL31.glTexBuffer(GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, this.tboBuffer); - GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, 0); + this.deleteBuffers(); + this.buffer = new VertexBuffer( FixedWidthFontRenderer.TYPE.getVertexFormat() ); + this.addMonitor(); + return true; - GlStateManager.bindBuffers(GL31.GL_TEXTURE_BUFFER, 0); - - this.addMonitor(); - return true; - } - - case VBO: - if (this.buffer != null) { + default: return false; - } - - this.deleteBuffers(); - this.buffer = new VertexBuffer(FixedWidthFontRenderer.TYPE.getVertexFormat()); - this.addMonitor(); - return true; - - default: - return false; } } - private void deleteBuffers() { + private void deleteBuffers() + { - if (this.tboBuffer != 0) { - RenderSystem.glDeleteBuffers(this.tboBuffer); + if( this.tboBuffer != 0 ) + { + RenderSystem.glDeleteBuffers( this.tboBuffer ); this.tboBuffer = 0; } - if (this.tboTexture != 0) { - GlStateManager.deleteTexture(this.tboTexture); + if( this.tboTexture != 0 ) + { + GlStateManager.deleteTexture( this.tboTexture ); this.tboTexture = 0; } - if (this.buffer != null) { + if( this.buffer != null ) + { this.buffer.close(); this.buffer = null; } } - private void addMonitor() { - synchronized (allMonitors) { - allMonitors.add(this); + private void addMonitor() + { + synchronized( allMonitors ) + { + allMonitors.add( this ); } } - @Environment (EnvType.CLIENT) - public void destroy() { - if (this.tboBuffer != 0 || this.buffer != null) { - synchronized (allMonitors) { - allMonitors.remove(this); + @Environment( EnvType.CLIENT ) + public void destroy() + { + if( this.tboBuffer != 0 || this.buffer != null ) + { + synchronized( allMonitors ) + { + allMonitors.remove( this ); } this.deleteBuffers(); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorEdgeState.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorEdgeState.java index af5600f58..6e2e83bbd 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorEdgeState.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorEdgeState.java @@ -6,40 +6,40 @@ package dan200.computercraft.shared.peripheral.monitor; -import static dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState.Flags.DOWN; -import static dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState.Flags.LEFT; -import static dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState.Flags.RIGHT; -import static dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState.Flags.UP; +import net.minecraft.util.StringIdentifiable; import javax.annotation.Nonnull; -import net.minecraft.util.StringIdentifiable; +import static dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState.Flags.*; -public enum MonitorEdgeState implements StringIdentifiable { - NONE("none", 0), +public enum MonitorEdgeState implements StringIdentifiable +{ + NONE( "none", 0 ), - L("l", LEFT), - R("r", RIGHT), - LR("lr", LEFT | RIGHT), - U("u", UP), - D("d", DOWN), + L( "l", LEFT ), + R( "r", RIGHT ), + LR( "lr", LEFT | RIGHT ), + U( "u", UP ), + D( "d", DOWN ), - UD("ud", UP | DOWN), - RD("rd", RIGHT | DOWN), - LD("ld", LEFT | DOWN), - RU("ru", RIGHT | UP), - LU("lu", LEFT | UP), + UD( "ud", UP | DOWN ), + RD( "rd", RIGHT | DOWN ), + LD( "ld", LEFT | DOWN ), + RU( "ru", RIGHT | UP ), + LU( "lu", LEFT | UP ), - LRD("lrd", LEFT | RIGHT | DOWN), - RUD("rud", RIGHT | UP | DOWN), - LUD("lud", LEFT | UP | DOWN), - LRU("lru", LEFT | RIGHT | UP), - LRUD("lrud", LEFT | RIGHT | UP | DOWN); + LRD( "lrd", LEFT | RIGHT | DOWN ), + RUD( "rud", RIGHT | UP | DOWN ), + LUD( "lud", LEFT | UP | DOWN ), + LRU( "lru", LEFT | RIGHT | UP ), + LRUD( "lrud", LEFT | RIGHT | UP | DOWN ); private static final MonitorEdgeState[] BY_FLAG = new MonitorEdgeState[16]; - static { - for (MonitorEdgeState state : values()) { + static + { + for( MonitorEdgeState state : values() ) + { BY_FLAG[state.flags] = state; } } @@ -47,22 +47,26 @@ public enum MonitorEdgeState implements StringIdentifiable { private final String name; private final int flags; - MonitorEdgeState(String name, int flags) { + MonitorEdgeState( String name, int flags ) + { this.name = name; this.flags = flags; } - public static MonitorEdgeState fromConnections(boolean up, boolean down, boolean left, boolean right) { + public static MonitorEdgeState fromConnections( boolean up, boolean down, boolean left, boolean right ) + { return BY_FLAG[(up ? UP : 0) | (down ? DOWN : 0) | (left ? LEFT : 0) | (right ? RIGHT : 0)]; } @Nonnull @Override - public String asString() { + public String asString() + { return this.name; } - static final class Flags { + static final class Flags + { static final int UP = 1 << 0; static final int DOWN = 1 << 1; static final int LEFT = 1 << 2; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java index 83e76c796..ee0191b03 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java @@ -6,9 +6,6 @@ package dan200.computercraft.shared.peripheral.monitor; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.LuaValues; @@ -17,6 +14,9 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.apis.TermMethods; import dan200.computercraft.core.terminal.Terminal; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Monitors are a block which act as a terminal, displaying information on one side. This allows them to be read and interacted with in-world without * opening a GUI. @@ -28,43 +28,50 @@ import dan200.computercraft.core.terminal.Terminal; * @cc.module monitor * @cc.usage Write "Hello, world!" to an adjacent monitor: * - *
    + * 
      *     local monitor = peripheral.find("monitor")
      *     monitor.setCursorPos(1, 1)
      *     monitor.write("Hello, world!")
      *     
    */ -public class MonitorPeripheral extends TermMethods implements IPeripheral { +public class MonitorPeripheral extends TermMethods implements IPeripheral +{ private final TileMonitor monitor; - public MonitorPeripheral(TileMonitor monitor) { + public MonitorPeripheral( TileMonitor monitor ) + { this.monitor = monitor; } @Nonnull @Override - public String getType() { + public String getType() + { return "monitor"; } @Override - public void attach(@Nonnull IComputerAccess computer) { - this.monitor.addComputer(computer); + public void attach( @Nonnull IComputerAccess computer ) + { + this.monitor.addComputer( computer ); } @Override - public void detach(@Nonnull IComputerAccess computer) { - this.monitor.removeComputer(computer); + public void detach( @Nonnull IComputerAccess computer ) + { + this.monitor.removeComputer( computer ); } @Nullable @Override - public Object getTarget() { + public Object getTarget() + { return this.monitor; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return other instanceof MonitorPeripheral && this.monitor == ((MonitorPeripheral) other).monitor; } @@ -75,7 +82,8 @@ public class MonitorPeripheral extends TermMethods implements IPeripheral { * @throws LuaException If the monitor cannot be found. */ @LuaFunction - public final double getTextScale() throws LuaException { + public final double getTextScale() throws LuaException + { return this.getMonitor().getTextScale() / 2.0; } @@ -87,35 +95,42 @@ public class MonitorPeripheral extends TermMethods implements IPeripheral { * @see #getTextScale() */ @LuaFunction - public final void setTextScale(double scaleArg) throws LuaException { - int scale = (int) (LuaValues.checkFinite(0, scaleArg) * 2.0); - if (scale < 1 || scale > 10) { - throw new LuaException("Expected number in range 0.5-5"); + public final void setTextScale( double scaleArg ) throws LuaException + { + int scale = (int) (LuaValues.checkFinite( 0, scaleArg ) * 2.0); + if( scale < 1 || scale > 10 ) + { + throw new LuaException( "Expected number in range 0.5-5" ); } - this.getMonitor().setTextScale(scale); + this.getMonitor().setTextScale( scale ); } @Nonnull - private ServerMonitor getMonitor() throws LuaException { + private ServerMonitor getMonitor() throws LuaException + { ServerMonitor monitor = this.monitor.getCachedServerMonitor(); - if (monitor == null) { - throw new LuaException("Monitor has been detached"); + if( monitor == null ) + { + throw new LuaException( "Monitor has been detached" ); } return monitor; } @Nonnull @Override - public Terminal getTerminal() throws LuaException { + public Terminal getTerminal() throws LuaException + { Terminal terminal = this.getMonitor().getTerminal(); - if (terminal == null) { - throw new LuaException("Monitor has been detached"); + if( terminal == null ) + { + throw new LuaException( "Monitor has been detached" ); } return terminal; } @Override - public boolean isColour() throws LuaException { + public boolean isColour() throws LuaException + { return this.getMonitor().isColour(); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java index c30d3a4d5..6d0dc360f 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java @@ -5,19 +5,20 @@ */ package dan200.computercraft.shared.peripheral.monitor; -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.render.TileEntityMonitorRenderer; import org.lwjgl.opengl.GL; +import javax.annotation.Nonnull; + /** * The render type to use for monitors. * * @see TileEntityMonitorRenderer * @see ClientMonitor */ -public enum MonitorRenderer { +public enum MonitorRenderer +{ /** * Determine the best monitor backend. */ @@ -44,32 +45,38 @@ public enum MonitorRenderer { * @return The current renderer. Will not return {@link MonitorRenderer#BEST}. */ @Nonnull - public static MonitorRenderer current() { + public static MonitorRenderer current() + { MonitorRenderer current = ComputerCraft.monitorRenderer; - switch (current) { - case BEST: - return best(); - case TBO: - checkCapabilities(); - if (!textureBuffer) { - ComputerCraft.log.warn("Texture buffers are not supported on your graphics card. Falling back to default."); - ComputerCraft.monitorRenderer = BEST; + switch( current ) + { + case BEST: return best(); - } + case TBO: + checkCapabilities(); + if( !textureBuffer ) + { + ComputerCraft.log.warn( "Texture buffers are not supported on your graphics card. Falling back to default." ); + ComputerCraft.monitorRenderer = BEST; + return best(); + } - return TBO; - default: - return current; + return TBO; + default: + return current; } } - private static MonitorRenderer best() { + private static MonitorRenderer best() + { checkCapabilities(); return textureBuffer ? TBO : VBO; } - private static void checkCapabilities() { - if (initialised) { + private static void checkCapabilities() + { + if( initialised ) + { return; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ServerMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ServerMonitor.java index 6914f2a0d..fb338fc27 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ServerMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ServerMonitor.java @@ -6,77 +6,90 @@ package dan200.computercraft.shared.peripheral.monitor; -import java.util.concurrent.atomic.AtomicBoolean; - import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.common.ServerTerminal; import dan200.computercraft.shared.util.TickScheduler; -public class ServerMonitor extends ServerTerminal { +import java.util.concurrent.atomic.AtomicBoolean; + +public class ServerMonitor extends ServerTerminal +{ private final TileMonitor origin; - private final AtomicBoolean resized = new AtomicBoolean(false); - private final AtomicBoolean changed = new AtomicBoolean(false); + private final AtomicBoolean resized = new AtomicBoolean( false ); + private final AtomicBoolean changed = new AtomicBoolean( false ); private int textScale = 2; - public ServerMonitor(boolean colour, TileMonitor origin) { - super(colour); + public ServerMonitor( boolean colour, TileMonitor origin ) + { + super( colour ); this.origin = origin; } @Override - protected void markTerminalChanged() { + protected void markTerminalChanged() + { super.markTerminalChanged(); this.markChanged(); } - private void markChanged() { - if (!this.changed.getAndSet(true)) { - TickScheduler.schedule(this.origin); + private void markChanged() + { + if( !this.changed.getAndSet( true ) ) + { + TickScheduler.schedule( this.origin ); } } - protected void clearChanged() { - this.changed.set(false); + protected void clearChanged() + { + this.changed.set( false ); } - public int getTextScale() { + public int getTextScale() + { return this.textScale; } - public synchronized void setTextScale(int textScale) { - if (this.textScale == textScale) { + public synchronized void setTextScale( int textScale ) + { + if( this.textScale == textScale ) + { return; } this.textScale = textScale; this.rebuild(); } - public synchronized void rebuild() { + public synchronized void rebuild() + { Terminal oldTerm = this.getTerminal(); int oldWidth = oldTerm == null ? -1 : oldTerm.getWidth(); int oldHeight = oldTerm == null ? -1 : oldTerm.getHeight(); double textScale = this.textScale * 0.5; int termWidth = - (int) Math.max(Math.round((this.origin.getWidth() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 6.0 * TileMonitor.RENDER_PIXEL_SCALE)), - 1.0); + (int) Math.max( Math.round( (this.origin.getWidth() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 6.0 * TileMonitor.RENDER_PIXEL_SCALE) ), + 1.0 ); int termHeight = - (int) Math.max(Math.round((this.origin.getHeight() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 9.0 * TileMonitor.RENDER_PIXEL_SCALE)), - 1.0); + (int) Math.max( Math.round( (this.origin.getHeight() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 9.0 * TileMonitor.RENDER_PIXEL_SCALE) ), + 1.0 ); - this.resize(termWidth, termHeight); - if (oldWidth != termWidth || oldHeight != termHeight) { + this.resize( termWidth, termHeight ); + if( oldWidth != termWidth || oldHeight != termHeight ) + { this.getTerminal().clear(); - this.resized.set(true); + this.resized.set( true ); this.markChanged(); } } - public boolean pollResized() { - return this.resized.getAndSet(false); + public boolean pollResized() + { + return this.resized.getAndSet( false ); } - public boolean pollTerminalChanged() { + public boolean pollTerminalChanged() + { this.update(); return this.hasTerminalChanged(); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java index d7331f5df..ee328608c 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.peripheral.monitor; -import java.util.HashSet; -import java.util.Set; - -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; @@ -20,7 +15,6 @@ import dan200.computercraft.shared.common.ServerTerminal; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.network.client.TerminalState; import dan200.computercraft.shared.util.TickScheduler; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -33,10 +27,12 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; +import java.util.HashSet; +import java.util.Set; -public class TileMonitor extends TileGeneric implements IPeripheralTile { +public class TileMonitor extends TileGeneric implements IPeripheralTile +{ public static final double RENDER_BORDER = 2.0 / 16.0; public static final double RENDER_MARGIN = 0.5 / 16.0; public static final double RENDER_PIXEL_SCALE = 1.0 / 64.0; @@ -62,35 +58,43 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { private int m_xIndex = 0; private int m_yIndex = 0; - public TileMonitor(BlockEntityType type, boolean advanced) { - super(type); + public TileMonitor( BlockEntityType type, boolean advanced ) + { + super( type ); this.advanced = advanced; } @Override - public void destroy() { + public void destroy() + { // TODO: Call this before using the block - if (this.m_destroyed) { + if( this.m_destroyed ) + { return; } this.m_destroyed = true; - if (!this.getWorld().isClient) { + if( !this.getWorld().isClient ) + { this.contractNeighbours(); } } @Override - public void markRemoved() { + public void markRemoved() + { super.markRemoved(); - if (this.m_clientMonitor != null && this.m_xIndex == 0 && this.m_yIndex == 0) { + if( this.m_clientMonitor != null && this.m_xIndex == 0 && this.m_yIndex == 0 ) + { this.m_clientMonitor.destroy(); } } @Override - public void onChunkUnloaded() { + public void onChunkUnloaded() + { super.onChunkUnloaded(); - if (this.m_clientMonitor != null && this.m_xIndex == 0 && this.m_yIndex == 0) { + if( this.m_clientMonitor != null && this.m_xIndex == 0 && this.m_yIndex == 0 ) + { this.m_clientMonitor.destroy(); } this.m_clientMonitor = null; @@ -98,15 +102,18 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - if (!player.isInSneakingPose() && this.getFront() == hit.getSide()) { - if (!this.getWorld().isClient) { - this.monitorTouched((float) (hit.getPos().x - hit.getBlockPos() - .getX()), - (float) (hit.getPos().y - hit.getBlockPos() - .getY()), - (float) (hit.getPos().z - hit.getBlockPos() - .getZ())); + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + if( !player.isInSneakingPose() && this.getFront() == hit.getSide() ) + { + if( !this.getWorld().isClient ) + { + this.monitorTouched( (float) (hit.getPos().x - hit.getBlockPos() + .getX()), + (float) (hit.getPos().y - hit.getBlockPos() + .getY()), + (float) (hit.getPos().z - hit.getBlockPos() + .getZ()) ); } return ActionResult.SUCCESS; } @@ -115,124 +122,148 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { } @Override - public void blockTick() { - if ( needsUpdate ) + public void blockTick() + { + if( needsUpdate ) { needsUpdate = false; updateNeighbors(); } - if (this.m_xIndex != 0 || this.m_yIndex != 0 || this.m_serverMonitor == null) { + if( this.m_xIndex != 0 || this.m_yIndex != 0 || this.m_serverMonitor == null ) + { return; } this.m_serverMonitor.clearChanged(); - if (this.m_serverMonitor.pollResized()) { - for (int x = 0; x < this.m_width; x++) { - for (int y = 0; y < this.m_height; y++) { - TileMonitor monitor = this.getNeighbour(x, y); - if (monitor == null) { + if( this.m_serverMonitor.pollResized() ) + { + for( int x = 0; x < this.m_width; x++ ) + { + for( int y = 0; y < this.m_height; y++ ) + { + TileMonitor monitor = this.getNeighbour( x, y ); + if( monitor == null ) + { continue; } - for (IComputerAccess computer : monitor.m_computers) { - computer.queueEvent("monitor_resize", computer.getAttachmentName()); + for( IComputerAccess computer : monitor.m_computers ) + { + computer.queueEvent( "monitor_resize", computer.getAttachmentName() ); } } } } - if (this.m_serverMonitor.pollTerminalChanged()) { + if( this.m_serverMonitor.pollTerminalChanged() ) + { this.updateBlock(); } } @Override - protected final void readDescription(@Nonnull CompoundTag nbt) { - super.readDescription(nbt); + protected final void readDescription( @Nonnull CompoundTag nbt ) + { + super.readDescription( nbt ); int oldXIndex = this.m_xIndex; int oldYIndex = this.m_yIndex; int oldWidth = this.m_width; int oldHeight = this.m_height; - this.m_xIndex = nbt.getInt(NBT_X); - this.m_yIndex = nbt.getInt(NBT_Y); - this.m_width = nbt.getInt(NBT_WIDTH); - this.m_height = nbt.getInt(NBT_HEIGHT); + this.m_xIndex = nbt.getInt( NBT_X ); + this.m_yIndex = nbt.getInt( NBT_Y ); + this.m_width = nbt.getInt( NBT_WIDTH ); + this.m_height = nbt.getInt( NBT_HEIGHT ); - if (oldXIndex != this.m_xIndex || oldYIndex != this.m_yIndex) { + if( oldXIndex != this.m_xIndex || oldYIndex != this.m_yIndex ) + { // If our index has changed then it's possible the origin monitor has changed. Thus // we'll clear our cache. If we're the origin then we'll need to remove the glList as well. - if (oldXIndex == 0 && oldYIndex == 0 && this.m_clientMonitor != null) { + if( oldXIndex == 0 && oldYIndex == 0 && this.m_clientMonitor != null ) + { this.m_clientMonitor.destroy(); } this.m_clientMonitor = null; } - if (this.m_xIndex == 0 && this.m_yIndex == 0) { + if( this.m_xIndex == 0 && this.m_yIndex == 0 ) + { // If we're the origin terminal then create it. - if (this.m_clientMonitor == null) { - this.m_clientMonitor = new ClientMonitor(this.advanced, this); + if( this.m_clientMonitor == null ) + { + this.m_clientMonitor = new ClientMonitor( this.advanced, this ); } - this.m_clientMonitor.readDescription(nbt); + this.m_clientMonitor.readDescription( nbt ); } - if (oldXIndex != this.m_xIndex || oldYIndex != this.m_yIndex || oldWidth != this.m_width || oldHeight != this.m_height) { + if( oldXIndex != this.m_xIndex || oldYIndex != this.m_yIndex || oldWidth != this.m_width || oldHeight != this.m_height ) + { // One of our properties has changed, so ensure we redraw the block this.updateBlock(); } } @Override - protected void writeDescription(@Nonnull CompoundTag nbt) { - super.writeDescription(nbt); - nbt.putInt(NBT_X, this.m_xIndex); - nbt.putInt(NBT_Y, this.m_yIndex); - nbt.putInt(NBT_WIDTH, this.m_width); - nbt.putInt(NBT_HEIGHT, this.m_height); + protected void writeDescription( @Nonnull CompoundTag nbt ) + { + super.writeDescription( nbt ); + nbt.putInt( NBT_X, this.m_xIndex ); + nbt.putInt( NBT_Y, this.m_yIndex ); + nbt.putInt( NBT_WIDTH, this.m_width ); + nbt.putInt( NBT_HEIGHT, this.m_height ); - if (this.m_xIndex == 0 && this.m_yIndex == 0 && this.m_serverMonitor != null) { - this.m_serverMonitor.writeDescription(nbt); + if( this.m_xIndex == 0 && this.m_yIndex == 0 && this.m_serverMonitor != null ) + { + this.m_serverMonitor.writeDescription( nbt ); } } - private TileMonitor getNeighbour(int x, int y) { + private TileMonitor getNeighbour( int x, int y ) + { BlockPos pos = this.getPos(); Direction right = this.getRight(); Direction down = this.getDown(); int xOffset = -this.m_xIndex + x; int yOffset = -this.m_yIndex + y; - return this.getSimilarMonitorAt(pos.offset(right, xOffset) - .offset(down, yOffset)); + return this.getSimilarMonitorAt( pos.offset( right, xOffset ) + .offset( down, yOffset ) ); } - public Direction getRight() { + public Direction getRight() + { return this.getDirection().rotateYCounterclockwise(); } - public Direction getDown() { + public Direction getDown() + { Direction orientation = this.getOrientation(); - if (orientation == Direction.NORTH) { + if( orientation == Direction.NORTH ) + { return Direction.UP; } return orientation == Direction.DOWN ? this.getDirection() : this.getDirection().getOpposite(); } - private TileMonitor getSimilarMonitorAt(BlockPos pos) { - if (pos.equals(this.getPos())) { + private TileMonitor getSimilarMonitorAt( BlockPos pos ) + { + if( pos.equals( this.getPos() ) ) + { return this; } int y = pos.getY(); World world = this.getWorld(); - if (world == null || !world.isChunkLoaded(pos)) { + if( world == null || !world.isChunkLoaded( pos ) ) + { return null; } - BlockEntity tile = world.getBlockEntity(pos); - if (!(tile instanceof TileMonitor)) { + BlockEntity tile = world.getBlockEntity( pos ); + if( !(tile instanceof TileMonitor) ) + { return null; } @@ -241,107 +272,128 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { } // region Sizing and placement stuff - public Direction getDirection() { + public Direction getDirection() + { // Ensure we're actually a monitor block. This _should_ always be the case, but sometimes there's // fun problems with the block being missing on the client. BlockState state = getCachedState(); return state.contains( BlockMonitor.FACING ) ? state.get( BlockMonitor.FACING ) : Direction.NORTH; } - public Direction getOrientation() { - return this.getCachedState().get(BlockMonitor.ORIENTATION); + public Direction getOrientation() + { + return this.getCachedState().get( BlockMonitor.ORIENTATION ); } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); - this.m_xIndex = nbt.getInt(NBT_X); - this.m_yIndex = nbt.getInt(NBT_Y); - this.m_width = nbt.getInt(NBT_WIDTH); - this.m_height = nbt.getInt(NBT_HEIGHT); + this.m_xIndex = nbt.getInt( NBT_X ); + this.m_yIndex = nbt.getInt( NBT_Y ); + this.m_width = nbt.getInt( NBT_WIDTH ); + this.m_height = nbt.getInt( NBT_HEIGHT ); } // Networking stuff @Nonnull @Override - public CompoundTag toTag(CompoundTag tag) { - tag.putInt(NBT_X, this.m_xIndex); - tag.putInt(NBT_Y, this.m_yIndex); - tag.putInt(NBT_WIDTH, this.m_width); - tag.putInt(NBT_HEIGHT, this.m_height); - return super.toTag(tag); + public CompoundTag toTag( CompoundTag tag ) + { + tag.putInt( NBT_X, this.m_xIndex ); + tag.putInt( NBT_Y, this.m_yIndex ); + tag.putInt( NBT_WIDTH, this.m_width ); + tag.putInt( NBT_HEIGHT, this.m_height ); + return super.toTag( tag ); } @Override - public double getRenderDistance() { + public double getRenderDistance() + { return ComputerCraft.monitorDistanceSq; } // Sizing and placement stuff @Override - public void cancelRemoval() { + public void cancelRemoval() + { super.cancelRemoval(); - TickScheduler.schedule(this); + TickScheduler.schedule( this ); } @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { + public IPeripheral getPeripheral( Direction side ) + { this.createServerMonitor(); // Ensure the monitor is created before doing anything else. - if (this.peripheral == null) { - this.peripheral = new MonitorPeripheral(this); + if( this.peripheral == null ) + { + this.peripheral = new MonitorPeripheral( this ); } return this.peripheral; } - public ServerMonitor getCachedServerMonitor() { + public ServerMonitor getCachedServerMonitor() + { return this.m_serverMonitor; } - private ServerMonitor getServerMonitor() { - if (this.m_serverMonitor != null) { + private ServerMonitor getServerMonitor() + { + if( this.m_serverMonitor != null ) + { return this.m_serverMonitor; } TileMonitor origin = this.getOrigin(); - if (origin == null) { + if( origin == null ) + { return null; } return this.m_serverMonitor = origin.m_serverMonitor; } - private ServerMonitor createServerMonitor() { - if (this.m_serverMonitor != null) { + private ServerMonitor createServerMonitor() + { + if( this.m_serverMonitor != null ) + { return this.m_serverMonitor; } - if (this.m_xIndex == 0 && this.m_yIndex == 0) { + if( this.m_xIndex == 0 && this.m_yIndex == 0 ) + { // If we're the origin, set up the new monitor - this.m_serverMonitor = new ServerMonitor(this.advanced, this); + this.m_serverMonitor = new ServerMonitor( this.advanced, this ); this.m_serverMonitor.rebuild(); // And propagate it to child monitors - for (int x = 0; x < this.m_width; x++) { - for (int y = 0; y < this.m_height; y++) { - TileMonitor monitor = this.getNeighbour(x, y); - if (monitor != null) { + for( int x = 0; x < this.m_width; x++ ) + { + for( int y = 0; y < this.m_height; y++ ) + { + TileMonitor monitor = this.getNeighbour( x, y ); + if( monitor != null ) + { monitor.m_serverMonitor = this.m_serverMonitor; } } } return this.m_serverMonitor; - } else { + } + else + { // Otherwise fetch the origin and attempt to get its monitor // Note this may load chunks, but we don't really have a choice here. BlockPos pos = this.getPos(); - BlockEntity te = this.world.getBlockEntity(pos.offset(this.getRight(), -this.m_xIndex) - .offset(this.getDown(), -this.m_yIndex)); - if (!(te instanceof TileMonitor)) { + BlockEntity te = this.world.getBlockEntity( pos.offset( this.getRight(), -this.m_xIndex ) + .offset( this.getDown(), -this.m_yIndex ) ); + if( !(te instanceof TileMonitor) ) + { return null; } @@ -349,69 +401,84 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { } } - public ClientMonitor getClientMonitor() { - if (this.m_clientMonitor != null) { + public ClientMonitor getClientMonitor() + { + if( this.m_clientMonitor != null ) + { return this.m_clientMonitor; } BlockPos pos = this.getPos(); - BlockEntity te = this.world.getBlockEntity(pos.offset(this.getRight(), -this.m_xIndex) - .offset(this.getDown(), -this.m_yIndex)); - if (!(te instanceof TileMonitor)) { + BlockEntity te = this.world.getBlockEntity( pos.offset( this.getRight(), -this.m_xIndex ) + .offset( this.getDown(), -this.m_yIndex ) ); + if( !(te instanceof TileMonitor) ) + { return null; } return this.m_clientMonitor = ((TileMonitor) te).m_clientMonitor; } - public final void read(TerminalState state) { - if (this.m_xIndex != 0 || this.m_yIndex != 0) { - ComputerCraft.log.warn("Receiving monitor state for non-origin terminal at {}", this.getPos()); + public final void read( TerminalState state ) + { + if( this.m_xIndex != 0 || this.m_yIndex != 0 ) + { + ComputerCraft.log.warn( "Receiving monitor state for non-origin terminal at {}", this.getPos() ); return; } - if (this.m_clientMonitor == null) { - this.m_clientMonitor = new ClientMonitor(this.advanced, this); + if( this.m_clientMonitor == null ) + { + this.m_clientMonitor = new ClientMonitor( this.advanced, this ); } - this.m_clientMonitor.read(state); + this.m_clientMonitor.read( state ); } - private void updateBlockState() { - this.getWorld().setBlockState(this.getPos(), - this.getCachedState().with(BlockMonitor.STATE, - MonitorEdgeState.fromConnections(this.m_yIndex < this.m_height - 1, - this.m_yIndex > 0, this.m_xIndex > 0, this.m_xIndex < this.m_width - 1)), - 2); + private void updateBlockState() + { + this.getWorld().setBlockState( this.getPos(), + this.getCachedState().with( BlockMonitor.STATE, + MonitorEdgeState.fromConnections( this.m_yIndex < this.m_height - 1, + this.m_yIndex > 0, this.m_xIndex > 0, this.m_xIndex < this.m_width - 1 ) ), + 2 ); } - public Direction getFront() { + public Direction getFront() + { Direction orientation = this.getOrientation(); return orientation == Direction.NORTH ? this.getDirection() : orientation; } - public int getWidth() { + public int getWidth() + { return this.m_width; } - public int getHeight() { + public int getHeight() + { return this.m_height; } - public int getXIndex() { + public int getXIndex() + { return this.m_xIndex; } - public int getYIndex() { + public int getYIndex() + { return this.m_yIndex; } - private TileMonitor getOrigin() { - return this.getNeighbour(0, 0); + private TileMonitor getOrigin() + { + return this.getNeighbour( 0, 0 ); } - private void resize(int width, int height) { + private void resize( int width, int height ) + { // If we're not already the origin then we'll need to generate a new terminal. - if (this.m_xIndex != 0 || this.m_yIndex != 0) { + if( this.m_xIndex != 0 || this.m_yIndex != 0 ) + { this.m_serverMonitor = null; } @@ -425,10 +492,13 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { // out of date, boolean needsTerminal = false; terminalCheck: - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - TileMonitor monitor = this.getNeighbour(x, y); - if (monitor != null && monitor.peripheral != null) { + for( int x = 0; x < width; x++ ) + { + for( int y = 0; y < height; y++ ) + { + TileMonitor monitor = this.getNeighbour( x, y ); + if( monitor != null && monitor.peripheral != null ) + { needsTerminal = true; break terminalCheck; } @@ -436,25 +506,33 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { } // Either delete the current monitor or sync a new one. - if (needsTerminal) { - if (this.m_serverMonitor == null) { - this.m_serverMonitor = new ServerMonitor(this.advanced, this); + if( needsTerminal ) + { + if( this.m_serverMonitor == null ) + { + this.m_serverMonitor = new ServerMonitor( this.advanced, this ); } - } else { + } + else + { this.m_serverMonitor = null; } // Update the terminal's width and height and rebuild it. This ensures the monitor // is consistent when syncing it to other monitors. - if (this.m_serverMonitor != null) { + if( this.m_serverMonitor != null ) + { this.m_serverMonitor.rebuild(); } // Update the other monitors, setting coordinates, dimensions and the server terminal - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - TileMonitor monitor = this.getNeighbour(x, y); - if (monitor == null) { + for( int x = 0; x < width; x++ ) + { + for( int y = 0; y < height; y++ ) + { + TileMonitor monitor = this.getNeighbour( x, y ); + if( monitor == null ) + { continue; } @@ -469,77 +547,93 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { } } - private boolean mergeLeft() { - TileMonitor left = this.getNeighbour(-1, 0); - if (left == null || left.m_yIndex != 0 || left.m_height != this.m_height) { + private boolean mergeLeft() + { + TileMonitor left = this.getNeighbour( -1, 0 ); + if( left == null || left.m_yIndex != 0 || left.m_height != this.m_height ) + { return false; } int width = left.m_width + this.m_width; - if (width > ComputerCraft.monitorWidth) { + if( width > ComputerCraft.monitorWidth ) + { return false; } TileMonitor origin = left.getOrigin(); - if (origin != null) { - origin.resize(width, this.m_height); + if( origin != null ) + { + origin.resize( width, this.m_height ); } left.expand(); return true; } - private boolean mergeRight() { - TileMonitor right = this.getNeighbour(this.m_width, 0); - if (right == null || right.m_yIndex != 0 || right.m_height != this.m_height) { + private boolean mergeRight() + { + TileMonitor right = this.getNeighbour( this.m_width, 0 ); + if( right == null || right.m_yIndex != 0 || right.m_height != this.m_height ) + { return false; } int width = this.m_width + right.m_width; - if (width > ComputerCraft.monitorWidth) { + if( width > ComputerCraft.monitorWidth ) + { return false; } TileMonitor origin = this.getOrigin(); - if (origin != null) { - origin.resize(width, this.m_height); + if( origin != null ) + { + origin.resize( width, this.m_height ); } this.expand(); return true; } - private boolean mergeUp() { - TileMonitor above = this.getNeighbour(0, this.m_height); - if (above == null || above.m_xIndex != 0 || above.m_width != this.m_width) { + private boolean mergeUp() + { + TileMonitor above = this.getNeighbour( 0, this.m_height ); + if( above == null || above.m_xIndex != 0 || above.m_width != this.m_width ) + { return false; } int height = above.m_height + this.m_height; - if (height > ComputerCraft.monitorHeight) { + if( height > ComputerCraft.monitorHeight ) + { return false; } TileMonitor origin = this.getOrigin(); - if (origin != null) { - origin.resize(this.m_width, height); + if( origin != null ) + { + origin.resize( this.m_width, height ); } this.expand(); return true; } - private boolean mergeDown() { - TileMonitor below = this.getNeighbour(0, -1); - if (below == null || below.m_xIndex != 0 || below.m_width != this.m_width) { + private boolean mergeDown() + { + TileMonitor below = this.getNeighbour( 0, -1 ); + if( below == null || below.m_xIndex != 0 || below.m_width != this.m_width ) + { return false; } int height = this.m_height + below.m_height; - if (height > ComputerCraft.monitorHeight) { + if( height > ComputerCraft.monitorHeight ) + { return false; } TileMonitor origin = below.getOrigin(); - if (origin != null) { - origin.resize(this.m_width, height); + if( origin != null ) + { + origin.resize( this.m_width, height ); } below.expand(); return true; @@ -557,70 +651,90 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { expand(); } - @SuppressWarnings ("StatementWithEmptyBody") - void expand() { - while (this.mergeLeft() || this.mergeRight() || this.mergeUp() || this.mergeDown()) { + @SuppressWarnings( "StatementWithEmptyBody" ) + void expand() + { + while( this.mergeLeft() || this.mergeRight() || this.mergeUp() || this.mergeDown() ) + { } } - void contractNeighbours() { + void contractNeighbours() + { this.visiting = true; - if (this.m_xIndex > 0) { - TileMonitor left = this.getNeighbour(this.m_xIndex - 1, this.m_yIndex); - if (left != null) { + if( this.m_xIndex > 0 ) + { + TileMonitor left = this.getNeighbour( this.m_xIndex - 1, this.m_yIndex ); + if( left != null ) + { left.contract(); } } - if (this.m_xIndex + 1 < this.m_width) { - TileMonitor right = this.getNeighbour(this.m_xIndex + 1, this.m_yIndex); - if (right != null) { + if( this.m_xIndex + 1 < this.m_width ) + { + TileMonitor right = this.getNeighbour( this.m_xIndex + 1, this.m_yIndex ); + if( right != null ) + { right.contract(); } } - if (this.m_yIndex > 0) { - TileMonitor below = this.getNeighbour(this.m_xIndex, this.m_yIndex - 1); - if (below != null) { + if( this.m_yIndex > 0 ) + { + TileMonitor below = this.getNeighbour( this.m_xIndex, this.m_yIndex - 1 ); + if( below != null ) + { below.contract(); } } - if (this.m_yIndex + 1 < this.m_height) { - TileMonitor above = this.getNeighbour(this.m_xIndex, this.m_yIndex + 1); - if (above != null) { + if( this.m_yIndex + 1 < this.m_height ) + { + TileMonitor above = this.getNeighbour( this.m_xIndex, this.m_yIndex + 1 ); + if( above != null ) + { above.contract(); } } this.visiting = false; } - void contract() { + void contract() + { int height = this.m_height; int width = this.m_width; TileMonitor origin = this.getOrigin(); - if (origin == null) { - TileMonitor right = width > 1 ? this.getNeighbour(1, 0) : null; - TileMonitor below = height > 1 ? this.getNeighbour(0, 1) : null; + if( origin == null ) + { + TileMonitor right = width > 1 ? this.getNeighbour( 1, 0 ) : null; + TileMonitor below = height > 1 ? this.getNeighbour( 0, 1 ) : null; - if (right != null) { - right.resize(width - 1, 1); + if( right != null ) + { + right.resize( width - 1, 1 ); } - if (below != null) { - below.resize(width, height - 1); + if( below != null ) + { + below.resize( width, height - 1 ); } - if (right != null) { + if( right != null ) + { right.expand(); } - if (below != null) { + if( below != null ) + { below.expand(); } return; } - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - TileMonitor monitor = origin.getNeighbour(x, y); - if (monitor != null) { + for( int y = 0; y < height; y++ ) + { + for( int x = 0; x < width; x++ ) + { + TileMonitor monitor = origin.getNeighbour( x, y ); + if( monitor != null ) + { continue; } @@ -630,34 +744,42 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { TileMonitor right = null; TileMonitor below = null; - if (y > 0) { + if( y > 0 ) + { above = origin; - above.resize(width, y); + above.resize( width, y ); } - if (x > 0) { - left = origin.getNeighbour(0, y); - left.resize(x, 1); + if( x > 0 ) + { + left = origin.getNeighbour( 0, y ); + left.resize( x, 1 ); } - if (x + 1 < width) { - right = origin.getNeighbour(x + 1, y); - right.resize(width - (x + 1), 1); + if( x + 1 < width ) + { + right = origin.getNeighbour( x + 1, y ); + right.resize( width - (x + 1), 1 ); } - if (y + 1 < height) { - below = origin.getNeighbour(0, y + 1); - below.resize(width, height - (y + 1)); + if( y + 1 < height ) + { + below = origin.getNeighbour( 0, y + 1 ); + below.resize( width, height - (y + 1) ); } // Re-expand - if (above != null) { + if( above != null ) + { above.expand(); } - if (left != null) { + if( left != null ) + { left.expand(); } - if (right != null) { + if( right != null ) + { right.expand(); } - if (below != null) { + if( below != null ) + { below.expand(); } return; @@ -666,46 +788,55 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { } // endregion - private void monitorTouched(float xPos, float yPos, float zPos) { - XYPair pair = XYPair.of(xPos, yPos, zPos, this.getDirection(), this.getOrientation()) - .add(this.m_xIndex, this.m_height - this.m_yIndex - 1); + private void monitorTouched( float xPos, float yPos, float zPos ) + { + XYPair pair = XYPair.of( xPos, yPos, zPos, this.getDirection(), this.getOrientation() ) + .add( this.m_xIndex, this.m_height - this.m_yIndex - 1 ); - if (pair.x > this.m_width - RENDER_BORDER || pair.y > this.m_height - RENDER_BORDER || pair.x < RENDER_BORDER || pair.y < RENDER_BORDER) { + if( pair.x > this.m_width - RENDER_BORDER || pair.y > this.m_height - RENDER_BORDER || pair.x < RENDER_BORDER || pair.y < RENDER_BORDER ) + { return; } ServerTerminal serverTerminal = this.getServerMonitor(); - if (serverTerminal == null || !serverTerminal.isColour()) { + if( serverTerminal == null || !serverTerminal.isColour() ) + { return; } Terminal originTerminal = serverTerminal.getTerminal(); - if (originTerminal == null) { + if( originTerminal == null ) + { return; } double xCharWidth = (this.m_width - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getWidth(); double yCharHeight = (this.m_height - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getHeight(); - int xCharPos = (int) Math.min(originTerminal.getWidth(), Math.max((pair.x - RENDER_BORDER - RENDER_MARGIN) / xCharWidth + 1.0, 1.0)); - int yCharPos = (int) Math.min(originTerminal.getHeight(), Math.max((pair.y - RENDER_BORDER - RENDER_MARGIN) / yCharHeight + 1.0, 1.0)); + int xCharPos = (int) Math.min( originTerminal.getWidth(), Math.max( (pair.x - RENDER_BORDER - RENDER_MARGIN) / xCharWidth + 1.0, 1.0 ) ); + int yCharPos = (int) Math.min( originTerminal.getHeight(), Math.max( (pair.y - RENDER_BORDER - RENDER_MARGIN) / yCharHeight + 1.0, 1.0 ) ); - for (int y = 0; y < this.m_height; y++) { - for (int x = 0; x < this.m_width; x++) { - TileMonitor monitor = this.getNeighbour(x, y); - if (monitor == null) { + for( int y = 0; y < this.m_height; y++ ) + { + for( int x = 0; x < this.m_width; x++ ) + { + TileMonitor monitor = this.getNeighbour( x, y ); + if( monitor == null ) + { continue; } - for (IComputerAccess computer : monitor.m_computers) { - computer.queueEvent("monitor_touch", computer.getAttachmentName(), xCharPos, yCharPos); + for( IComputerAccess computer : monitor.m_computers ) + { + computer.queueEvent( "monitor_touch", computer.getAttachmentName(), xCharPos, yCharPos ); } } } } - void addComputer(IComputerAccess computer) { - this.m_computers.add(computer); + void addComputer( IComputerAccess computer ) + { + this.m_computers.add( computer ); } // @Nonnull @@ -733,7 +864,8 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { // } // } - void removeComputer(IComputerAccess computer) { - this.m_computers.remove(computer); + void removeComputer( IComputerAccess computer ) + { + this.m_computers.remove( computer ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/XYPair.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/XYPair.java index 894333766..8aa24a4b3 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/XYPair.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/XYPair.java @@ -8,59 +8,67 @@ package dan200.computercraft.shared.peripheral.monitor; import net.minecraft.util.math.Direction; -public class XYPair { +public class XYPair +{ public final float x; public final float y; - public XYPair(float x, float y) { + public XYPair( float x, float y ) + { this.x = x; this.y = y; } - public static XYPair of(float xPos, float yPos, float zPos, Direction facing, Direction orientation) { - switch (orientation) { - case NORTH: - switch (facing) { + public static XYPair of( float xPos, float yPos, float zPos, Direction facing, Direction orientation ) + { + switch( orientation ) + { case NORTH: - return new XYPair(1 - xPos, 1 - yPos); - case SOUTH: - return new XYPair(xPos, 1 - yPos); - case WEST: - return new XYPair(zPos, 1 - yPos); - case EAST: - return new XYPair(1 - zPos, 1 - yPos); - } - break; - case DOWN: - switch (facing) { - case NORTH: - return new XYPair(1 - xPos, zPos); - case SOUTH: - return new XYPair(xPos, 1 - zPos); - case WEST: - return new XYPair(zPos, xPos); - case EAST: - return new XYPair(1 - zPos, 1 - xPos); - } - break; - case UP: - switch (facing) { - case NORTH: - return new XYPair(1 - xPos, 1 - zPos); - case SOUTH: - return new XYPair(xPos, zPos); - case WEST: - return new XYPair(zPos, 1 - xPos); - case EAST: - return new XYPair(1 - zPos, xPos); - } - break; + switch( facing ) + { + case NORTH: + return new XYPair( 1 - xPos, 1 - yPos ); + case SOUTH: + return new XYPair( xPos, 1 - yPos ); + case WEST: + return new XYPair( zPos, 1 - yPos ); + case EAST: + return new XYPair( 1 - zPos, 1 - yPos ); + } + break; + case DOWN: + switch( facing ) + { + case NORTH: + return new XYPair( 1 - xPos, zPos ); + case SOUTH: + return new XYPair( xPos, 1 - zPos ); + case WEST: + return new XYPair( zPos, xPos ); + case EAST: + return new XYPair( 1 - zPos, 1 - xPos ); + } + break; + case UP: + switch( facing ) + { + case NORTH: + return new XYPair( 1 - xPos, 1 - zPos ); + case SOUTH: + return new XYPair( xPos, zPos ); + case WEST: + return new XYPair( zPos, 1 - xPos ); + case EAST: + return new XYPair( 1 - zPos, xPos ); + } + break; } - return new XYPair(xPos, zPos); + return new XYPair( xPos, zPos ); } - public XYPair add(float x, float y) { - return new XYPair(this.x + x, this.y + y); + public XYPair add( float x, float y ) + { + return new XYPair( this.x + x, this.y + y ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java index 59e4cbb78..a9f91b35b 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java @@ -6,12 +6,8 @@ package dan200.computercraft.shared.peripheral.printer; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -29,54 +25,68 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class BlockPrinter extends BlockGeneric { - static final BooleanProperty TOP = BooleanProperty.of("top"); - static final BooleanProperty BOTTOM = BooleanProperty.of("bottom"); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class BlockPrinter extends BlockGeneric +{ + static final BooleanProperty TOP = BooleanProperty.of( "top" ); + static final BooleanProperty BOTTOM = BooleanProperty.of( "bottom" ); private static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - public BlockPrinter(Settings settings) { - super(settings, ComputerCraftRegistry.ModTiles.PRINTER); - this.setDefaultState(this.getStateManager().getDefaultState() - .with(FACING, Direction.NORTH) - .with(TOP, false) - .with(BOTTOM, false)); + public BlockPrinter( Settings settings ) + { + super( settings, ComputerCraftRegistry.ModTiles.PRINTER ); + this.setDefaultState( this.getStateManager().getDefaultState() + .with( FACING, Direction.NORTH ) + .with( TOP, false ) + .with( BOTTOM, false ) ); } @Nullable @Override - public BlockState getPlacementState(ItemPlacementContext placement) { - return this.getDefaultState().with(FACING, - placement.getPlayerFacing() - .getOpposite()); + public BlockState getPlacementState( ItemPlacementContext placement ) + { + return this.getDefaultState().with( FACING, + placement.getPlayerFacing() + .getOpposite() ); } @Override - public void afterBreak(@Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te - , @Nonnull ItemStack stack) { - if (te instanceof Nameable && ((Nameable) te).hasCustomName()) { - player.incrementStat(Stats.MINED.getOrCreateStat(this)); - player.addExhaustion(0.005F); + public void afterBreak( @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te + , @Nonnull ItemStack stack ) + { + if( te instanceof Nameable && ((Nameable) te).hasCustomName() ) + { + player.incrementStat( Stats.MINED.getOrCreateStat( this ) ); + player.addExhaustion( 0.005F ); - ItemStack result = new ItemStack(this); - result.setCustomName(((Nameable) te).getCustomName()); - dropStack(world, pos, result); - } else { - super.afterBreak(world, player, pos, state, te, stack); + ItemStack result = new ItemStack( this ); + result.setCustomName( ((Nameable) te).getCustomName() ); + dropStack( world, pos, result ); + } + else + { + super.afterBreak( world, player, pos, state, te, stack ); } } @Override - public void onPlaced(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, ItemStack stack) { - if (stack.hasCustomName()) { - BlockEntity tileentity = world.getBlockEntity(pos); - if (tileentity instanceof TilePrinter) { + public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, ItemStack stack ) + { + if( stack.hasCustomName() ) + { + BlockEntity tileentity = world.getBlockEntity( pos ); + if( tileentity instanceof TilePrinter ) + { ((TilePrinter) tileentity).customName = stack.getName(); } } } @Override - protected void appendProperties(StateManager.Builder properties) { - properties.add(FACING, TOP, BOTTOM); + protected void appendProperties( StateManager.Builder properties ) + { + properties.add( FACING, TOP, BOTTOM ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java index 03f234f6b..f2f322e7e 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java @@ -6,11 +6,8 @@ package dan200.computercraft.shared.peripheral.printer; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.util.SingleIntArray; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -21,99 +18,126 @@ import net.minecraft.screen.PropertyDelegate; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; -public class ContainerPrinter extends ScreenHandler { +import javax.annotation.Nonnull; + +public class ContainerPrinter extends ScreenHandler +{ private final Inventory inventory; private final PropertyDelegate properties; - public ContainerPrinter(int id, PlayerInventory player) { - this(id, player, new SimpleInventory(TilePrinter.SLOTS), new ArrayPropertyDelegate(1)); + public ContainerPrinter( int id, PlayerInventory player ) + { + this( id, player, new SimpleInventory( TilePrinter.SLOTS ), new ArrayPropertyDelegate( 1 ) ); } - private ContainerPrinter(int id, PlayerInventory player, Inventory inventory, PropertyDelegate properties) { - super(ComputerCraftRegistry.ModContainers.PRINTER, id); + private ContainerPrinter( int id, PlayerInventory player, Inventory inventory, PropertyDelegate properties ) + { + super( ComputerCraftRegistry.ModContainers.PRINTER, id ); this.properties = properties; this.inventory = inventory; - this.addProperties(properties); + this.addProperties( properties ); // Ink slot - this.addSlot(new Slot(inventory, 0, 13, 35)); + this.addSlot( new Slot( inventory, 0, 13, 35 ) ); // In-tray - for (int x = 0; x < 6; x++) { - this.addSlot(new Slot(inventory, x + 1, 61 + x * 18, 22)); + for( int x = 0; x < 6; x++ ) + { + this.addSlot( new Slot( inventory, x + 1, 61 + x * 18, 22 ) ); } // Out-tray - for (int x = 0; x < 6; x++) { - this.addSlot(new Slot(inventory, x + 7, 61 + x * 18, 49)); + for( int x = 0; x < 6; x++ ) + { + this.addSlot( new Slot( inventory, x + 7, 61 + x * 18, 49 ) ); } // Player inv - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 9; x++) { - this.addSlot(new Slot(player, x + y * 9 + 9, 8 + x * 18, 84 + y * 18)); + for( int y = 0; y < 3; y++ ) + { + for( int x = 0; x < 9; x++ ) + { + this.addSlot( new Slot( player, x + y * 9 + 9, 8 + x * 18, 84 + y * 18 ) ); } } // Player hotbar - for (int x = 0; x < 9; x++) { - this.addSlot(new Slot(player, x, 8 + x * 18, 142)); + for( int x = 0; x < 9; x++ ) + { + this.addSlot( new Slot( player, x, 8 + x * 18, 142 ) ); } } - public ContainerPrinter(int id, PlayerInventory player, TilePrinter printer) { - this(id, player, printer, (SingleIntArray) (() -> printer.isPrinting() ? 1 : 0)); + public ContainerPrinter( int id, PlayerInventory player, TilePrinter printer ) + { + this( id, player, printer, (SingleIntArray) (() -> printer.isPrinting() ? 1 : 0) ); } - public boolean isPrinting() { - return this.properties.get(0) != 0; + public boolean isPrinting() + { + return this.properties.get( 0 ) != 0; } @Nonnull @Override - public ItemStack transferSlot(@Nonnull PlayerEntity player, int index) { - Slot slot = this.slots.get(index); - if (slot == null || !slot.hasStack()) { + public ItemStack transferSlot( @Nonnull PlayerEntity player, int index ) + { + Slot slot = this.slots.get( index ); + if( slot == null || !slot.hasStack() ) + { return ItemStack.EMPTY; } ItemStack stack = slot.getStack(); ItemStack result = stack.copy(); - if (index < 13) { + if( index < 13 ) + { // Transfer from printer to inventory - if (!this.insertItem(stack, 13, 49, true)) { + if( !this.insertItem( stack, 13, 49, true ) ) + { return ItemStack.EMPTY; } - } else { + } + else + { // Transfer from inventory to printer - if( TilePrinter.isInk( stack ) ) { - if (!this.insertItem(stack, 0, 1, false)) { + if( TilePrinter.isInk( stack ) ) + { + if( !this.insertItem( stack, 0, 1, false ) ) + { return ItemStack.EMPTY; } - } else //if is paper + } + else //if is paper { - if (!this.insertItem(stack, 1, 13, false)) { + if( !this.insertItem( stack, 1, 13, false ) ) + { return ItemStack.EMPTY; } } } - if (stack.isEmpty()) { - slot.setStack(ItemStack.EMPTY); - } else { + if( stack.isEmpty() ) + { + slot.setStack( ItemStack.EMPTY ); + } + else + { slot.markDirty(); } - if (stack.getCount() == result.getCount()) { + if( stack.getCount() == result.getCount() ) + { return ItemStack.EMPTY; } - slot.onTakeItem(player, stack); + slot.onTakeItem( player, stack ); return result; } @Override - public boolean canUse(@Nonnull PlayerEntity player) { - return this.inventory.canPlayerUse(player); + public boolean canUse( @Nonnull PlayerEntity player ) + { + return this.inventory.canPlayerUse( player ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java index aa3c2248a..e0cb64942 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java @@ -6,10 +6,6 @@ package dan200.computercraft.shared.peripheral.printer; -import java.util.Optional; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; @@ -17,21 +13,27 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.util.StringUtil; +import javax.annotation.Nonnull; +import java.util.Optional; + /** * The printer peripheral allows pages and books to be printed. * * @cc.module printer */ -public class PrinterPeripheral implements IPeripheral { +public class PrinterPeripheral implements IPeripheral +{ private final TilePrinter printer; - public PrinterPeripheral(TilePrinter printer) { + public PrinterPeripheral( TilePrinter printer ) + { this.printer = printer; } @Nonnull @Override - public String getType() { + public String getType() + { return "printer"; } @@ -43,12 +45,14 @@ public class PrinterPeripheral implements IPeripheral { @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return this.printer; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return other instanceof PrinterPeripheral && ((PrinterPeripheral) other).printer == this.printer; } @@ -60,18 +64,21 @@ public class PrinterPeripheral implements IPeripheral { * @cc.tparam string|number ... The values to write to the page. */ @LuaFunction - public final void write(IArguments arguments) throws LuaException { - String text = StringUtil.toString(arguments.get(0)); + public final void write( IArguments arguments ) throws LuaException + { + String text = StringUtil.toString( arguments.get( 0 ) ); Terminal page = this.getCurrentPage(); - page.write(text); - page.setCursorPos(page.getCursorX() + text.length(), page.getCursorY()); + page.write( text ); + page.setCursorPos( page.getCursorX() + text.length(), page.getCursorY() ); } @Nonnull - private Terminal getCurrentPage() throws LuaException { + private Terminal getCurrentPage() throws LuaException + { Terminal currentPage = this.printer.getCurrentPage(); - if (currentPage == null) { - throw new LuaException("Page not started"); + if( currentPage == null ) + { + throw new LuaException( "Page not started" ); } return currentPage; } @@ -85,7 +92,8 @@ public class PrinterPeripheral implements IPeripheral { * @cc.treturn number The Y position of the cursor. */ @LuaFunction - public final Object[] getCursorPos() throws LuaException { + public final Object[] getCursorPos() throws LuaException + { Terminal page = this.getCurrentPage(); int x = page.getCursorX(); int y = page.getCursorY(); @@ -103,9 +111,10 @@ public class PrinterPeripheral implements IPeripheral { * @throws LuaException If a page isn't being printed. */ @LuaFunction - public final void setCursorPos(int x, int y) throws LuaException { + public final void setCursorPos( int x, int y ) throws LuaException + { Terminal page = this.getCurrentPage(); - page.setCursorPos(x - 1, y - 1); + page.setCursorPos( x - 1, y - 1 ); } /** @@ -117,7 +126,8 @@ public class PrinterPeripheral implements IPeripheral { * @cc.treturn number The height of the page. */ @LuaFunction - public final Object[] getPageSize() throws LuaException { + public final Object[] getPageSize() throws LuaException + { Terminal page = this.getCurrentPage(); int width = page.getWidth(); int height = page.getHeight(); @@ -132,8 +142,9 @@ public class PrinterPeripheral implements IPeripheral { * * @return Whether a new page could be started. */ - @LuaFunction (mainThread = true) - public final boolean newPage() { + @LuaFunction( mainThread = true ) + public final boolean newPage() + { return this.printer.startNewPage(); } @@ -143,8 +154,9 @@ public class PrinterPeripheral implements IPeripheral { * @return Whether the page could be successfully finished. * @throws LuaException If a page isn't being printed. */ - @LuaFunction (mainThread = true) - public final boolean endPage() throws LuaException { + @LuaFunction( mainThread = true ) + public final boolean endPage() throws LuaException + { this.getCurrentPage(); return this.printer.endCurrentPage(); } @@ -156,9 +168,10 @@ public class PrinterPeripheral implements IPeripheral { * @throws LuaException If a page isn't being printed. */ @LuaFunction - public final void setPageTitle(Optional title) throws LuaException { + public final void setPageTitle( Optional title ) throws LuaException + { this.getCurrentPage(); - this.printer.setPageTitle(StringUtil.normaliseLabel(title.orElse(""))); + this.printer.setPageTitle( StringUtil.normaliseLabel( title.orElse( "" ) ) ); } /** @@ -167,7 +180,8 @@ public class PrinterPeripheral implements IPeripheral { * @return The amount of ink available to print with. */ @LuaFunction - public final int getInkLevel() { + public final int getInkLevel() + { return this.printer.getInkLevel(); } @@ -177,7 +191,8 @@ public class PrinterPeripheral implements IPeripheral { * @return The amount of paper available to print with. */ @LuaFunction - public final int getPaperLevel() { + public final int getPaperLevel() + { return this.printer.getPaperLevel(); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java index 0cbe6c45e..a5198248d 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -6,9 +6,6 @@ package dan200.computercraft.shared.peripheral.printer; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheralTile; import dan200.computercraft.core.terminal.Terminal; @@ -18,13 +15,11 @@ import dan200.computercraft.shared.util.ColourUtils; import dan200.computercraft.shared.util.DefaultSidedInventory; import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventories; -import net.minecraft.item.DyeItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -42,7 +37,11 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, IPeripheralTile, Nameable, NamedScreenHandlerFactory { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, IPeripheralTile, Nameable, NamedScreenHandlerFactory +{ static final int SLOTS = 13; private static final String NBT_NAME = "CustomName"; private static final String NBT_PRINTING = "Printing"; @@ -63,142 +62,169 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent 5, 6 }; - private static final int[] SIDE_SLOTS = new int[] {0}; - private final DefaultedList m_inventory = DefaultedList.ofSize(SLOTS, ItemStack.EMPTY); - private final ItemStorage m_itemHandlerAll = ItemStorage.wrap(this); - private final Terminal m_page = new Terminal(ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE); + private static final int[] SIDE_SLOTS = new int[] { 0 }; + private final DefaultedList m_inventory = DefaultedList.ofSize( SLOTS, ItemStack.EMPTY ); + private final ItemStorage m_itemHandlerAll = ItemStorage.wrap( this ); + private final Terminal m_page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE ); Text customName; private String m_pageTitle = ""; private boolean m_printing = false; - public TilePrinter(BlockEntityType type) { - super(type); + public TilePrinter( BlockEntityType type ) + { + super( type ); } @Override - public void destroy() { + public void destroy() + { this.ejectContents(); } @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - if (player.isInSneakingPose()) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + if( player.isInSneakingPose() ) + { return ActionResult.PASS; } - if (!this.getWorld().isClient) { - player.openHandledScreen(this); + if( !this.getWorld().isClient ) + { + player.openHandledScreen( this ); } return ActionResult.SUCCESS; } - private void ejectContents() { - for (int i = 0; i < 13; i++) { - ItemStack stack = this.m_inventory.get(i); - if (!stack.isEmpty()) { + private void ejectContents() + { + for( int i = 0; i < 13; i++ ) + { + ItemStack stack = this.m_inventory.get( i ); + if( !stack.isEmpty() ) + { // Remove the stack from the inventory - this.setStack(i, ItemStack.EMPTY); + this.setStack( i, ItemStack.EMPTY ); // Spawn the item in the world - WorldUtil.dropItemStack(stack, this.getWorld(), - Vec3d.of(this.getPos()) - .add(0.5, 0.75, 0.5)); + WorldUtil.dropItemStack( stack, this.getWorld(), + Vec3d.of( this.getPos() ) + .add( 0.5, 0.75, 0.5 ) ); } } } - private void updateBlockState() { + private void updateBlockState() + { boolean top = false, bottom = false; - for (int i = 1; i < 7; i++) { - ItemStack stack = this.m_inventory.get(i); - if (!stack.isEmpty() && isPaper(stack)) { + for( int i = 1; i < 7; i++ ) + { + ItemStack stack = this.m_inventory.get( i ); + if( !stack.isEmpty() && isPaper( stack ) ) + { top = true; break; } } - for (int i = 7; i < 13; i++) { - ItemStack stack = this.m_inventory.get(i); - if (!stack.isEmpty() && isPaper(stack)) { + for( int i = 7; i < 13; i++ ) + { + ItemStack stack = this.m_inventory.get( i ); + if( !stack.isEmpty() && isPaper( stack ) ) + { bottom = true; break; } } - this.updateBlockState(top, bottom); + this.updateBlockState( top, bottom ); } - private static boolean isPaper(@Nonnull ItemStack stack) { + private static boolean isPaper( @Nonnull ItemStack stack ) + { Item item = stack.getItem(); return item == Items.PAPER || (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE); } - private void updateBlockState(boolean top, boolean bottom) { - if (this.removed) { + private void updateBlockState( boolean top, boolean bottom ) + { + if( this.removed ) + { return; } BlockState state = this.getCachedState(); - if (state.get(BlockPrinter.TOP) == top & state.get(BlockPrinter.BOTTOM) == bottom) { + if( state.get( BlockPrinter.TOP ) == top & state.get( BlockPrinter.BOTTOM ) == bottom ) + { return; } - this.getWorld().setBlockState(this.getPos(), - state.with(BlockPrinter.TOP, top) - .with(BlockPrinter.BOTTOM, bottom)); + this.getWorld().setBlockState( this.getPos(), + state.with( BlockPrinter.TOP, top ) + .with( BlockPrinter.BOTTOM, bottom ) ); } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); - this.customName = nbt.contains(NBT_NAME) ? Text.Serializer.fromJson(nbt.getString(NBT_NAME)) : null; + this.customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; // Read page - synchronized (this.m_page) { - this.m_printing = nbt.getBoolean(NBT_PRINTING); - this.m_pageTitle = nbt.getString(NBT_PAGE_TITLE); - this.m_page.readFromNBT(nbt); + synchronized( this.m_page ) + { + this.m_printing = nbt.getBoolean( NBT_PRINTING ); + this.m_pageTitle = nbt.getString( NBT_PAGE_TITLE ); + this.m_page.readFromNBT( nbt ); } // Read inventory - Inventories.fromTag(nbt, this.m_inventory); + Inventories.fromTag( nbt, this.m_inventory ); } @Nonnull @Override - public CompoundTag toTag(@Nonnull CompoundTag nbt) { - if (this.customName != null) { - nbt.putString(NBT_NAME, Text.Serializer.toJson(this.customName)); + public CompoundTag toTag( @Nonnull CompoundTag nbt ) + { + if( this.customName != null ) + { + nbt.putString( NBT_NAME, Text.Serializer.toJson( this.customName ) ); } // Write page - synchronized (this.m_page) { - nbt.putBoolean(NBT_PRINTING, this.m_printing); - nbt.putString(NBT_PAGE_TITLE, this.m_pageTitle); - this.m_page.writeToNBT(nbt); + synchronized( this.m_page ) + { + nbt.putBoolean( NBT_PRINTING, this.m_printing ); + nbt.putString( NBT_PAGE_TITLE, this.m_pageTitle ); + this.m_page.writeToNBT( nbt ); } // Write inventory - Inventories.toTag(nbt, this.m_inventory); + Inventories.toTag( nbt, this.m_inventory ); - return super.toTag(nbt); + return super.toTag( nbt ); } - boolean isPrinting() { + boolean isPrinting() + { return this.m_printing; } // IInventory implementation @Override - public int size() { + public int size() + { return this.m_inventory.size(); } @Override - public boolean isEmpty() { - for (ItemStack stack : this.m_inventory) { - if (!stack.isEmpty()) { + public boolean isEmpty() + { + for( ItemStack stack : this.m_inventory ) + { + if( !stack.isEmpty() ) + { return false; } } @@ -207,27 +233,32 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Nonnull @Override - public ItemStack getStack(int slot) { - return this.m_inventory.get(slot); + public ItemStack getStack( int slot ) + { + return this.m_inventory.get( slot ); } @Nonnull @Override - public ItemStack removeStack(int slot, int count) { - ItemStack stack = this.m_inventory.get(slot); - if (stack.isEmpty()) { + public ItemStack removeStack( int slot, int count ) + { + ItemStack stack = this.m_inventory.get( slot ); + if( stack.isEmpty() ) + { return ItemStack.EMPTY; } - if (stack.getCount() <= count) { - this.setStack(slot, ItemStack.EMPTY); + if( stack.getCount() <= count ) + { + this.setStack( slot, ItemStack.EMPTY ); return stack; } - ItemStack part = stack.split(count); - if (this.m_inventory.get(slot) - .isEmpty()) { - this.m_inventory.set(slot, ItemStack.EMPTY); + ItemStack part = stack.split( count ); + if( this.m_inventory.get( slot ) + .isEmpty() ) + { + this.m_inventory.set( slot, ItemStack.EMPTY ); this.updateBlockState(); } this.markDirty(); @@ -236,9 +267,10 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Nonnull @Override - public ItemStack removeStack(int slot) { - ItemStack result = this.m_inventory.get(slot); - this.m_inventory.set(slot, ItemStack.EMPTY); + public ItemStack removeStack( int slot ) + { + ItemStack result = this.m_inventory.get( slot ); + this.m_inventory.set( slot, ItemStack.EMPTY ); this.markDirty(); this.updateBlockState(); return result; @@ -247,101 +279,127 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent // ISidedInventory implementation @Override - public void setStack(int slot, @Nonnull ItemStack stack) { - this.m_inventory.set(slot, stack); + public void setStack( int slot, @Nonnull ItemStack stack ) + { + this.m_inventory.set( slot, stack ); this.markDirty(); this.updateBlockState(); } @Override - public boolean canPlayerUse(@Nonnull PlayerEntity playerEntity) { - return this.isUsable(playerEntity, false); + public boolean canPlayerUse( @Nonnull PlayerEntity playerEntity ) + { + return this.isUsable( playerEntity, false ); } @Override - public void clear() { - for (int i = 0; i < this.m_inventory.size(); i++) { - this.m_inventory.set(i, ItemStack.EMPTY); + public void clear() + { + for( int i = 0; i < this.m_inventory.size(); i++ ) + { + this.m_inventory.set( i, ItemStack.EMPTY ); } this.markDirty(); this.updateBlockState(); } @Override - public boolean isValid(int slot, @Nonnull ItemStack stack) { - if (slot == 0) { - return isInk(stack); - } else if (slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1]) { - return isPaper(stack); - } else { + public boolean isValid( int slot, @Nonnull ItemStack stack ) + { + if( slot == 0 ) + { + return isInk( stack ); + } + else if( slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1] ) + { + return isPaper( stack ); + } + else + { return false; } } - static boolean isInk(@Nonnull ItemStack stack) { + static boolean isInk( @Nonnull ItemStack stack ) + { return ColourUtils.getStackColour( stack ) != null; } @Nonnull @Override - public int[] getAvailableSlots(@Nonnull Direction side) { - switch (side) { - case DOWN: // Bottom (Out tray) - return BOTTOM_SLOTS; - case UP: // Top (In tray) - return TOP_SLOTS; - default: // Sides (Ink) - return SIDE_SLOTS; + public int[] getAvailableSlots( @Nonnull Direction side ) + { + switch( side ) + { + case DOWN: // Bottom (Out tray) + return BOTTOM_SLOTS; + case UP: // Top (In tray) + return TOP_SLOTS; + default: // Sides (Ink) + return SIDE_SLOTS; } } @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { - return new PrinterPeripheral(this); + public IPeripheral getPeripheral( Direction side ) + { + return new PrinterPeripheral( this ); } @Nullable - Terminal getCurrentPage() { - synchronized (this.m_page) { + Terminal getCurrentPage() + { + synchronized( this.m_page ) + { return this.m_printing ? this.m_page : null; } } - boolean startNewPage() { - synchronized (this.m_page) { - if (!this.canInputPage()) { + boolean startNewPage() + { + synchronized( this.m_page ) + { + if( !this.canInputPage() ) + { return false; } - if (this.m_printing && !this.outputPage()) { + if( this.m_printing && !this.outputPage() ) + { return false; } return this.inputPage(); } } - boolean endCurrentPage() { - synchronized (this.m_page) { + boolean endCurrentPage() + { + synchronized( this.m_page ) + { return this.m_printing && this.outputPage(); } } - private boolean outputPage() { + private boolean outputPage() + { int height = this.m_page.getHeight(); String[] lines = new String[height]; String[] colours = new String[height]; - for (int i = 0; i < height; i++) { - lines[i] = this.m_page.getLine(i) - .toString(); - colours[i] = this.m_page.getTextColourLine(i) - .toString(); + for( int i = 0; i < height; i++ ) + { + lines[i] = this.m_page.getLine( i ) + .toString(); + colours[i] = this.m_page.getTextColourLine( i ) + .toString(); } - ItemStack stack = ItemPrintout.createSingleFromTitleAndText(this.m_pageTitle, lines, colours); - for (int slot : BOTTOM_SLOTS) { - if (this.m_inventory.get(slot) - .isEmpty()) { - this.setStack(slot, stack); + ItemStack stack = ItemPrintout.createSingleFromTitleAndText( this.m_pageTitle, lines, colours ); + for( int slot : BOTTOM_SLOTS ) + { + if( this.m_inventory.get( slot ) + .isEmpty() ) + { + this.setStack( slot, stack ); this.m_printing = false; return true; } @@ -349,43 +407,54 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent return false; } - int getInkLevel() { - ItemStack inkStack = this.m_inventory.get(0); - return isInk(inkStack) ? inkStack.getCount() : 0; + int getInkLevel() + { + ItemStack inkStack = this.m_inventory.get( 0 ); + return isInk( inkStack ) ? inkStack.getCount() : 0; } - int getPaperLevel() { + int getPaperLevel() + { int count = 0; - for (int i = 1; i < 7; i++) { - ItemStack paperStack = this.m_inventory.get(i); - if (isPaper(paperStack)) { + for( int i = 1; i < 7; i++ ) + { + ItemStack paperStack = this.m_inventory.get( i ); + if( isPaper( paperStack ) ) + { count += paperStack.getCount(); } } return count; } - void setPageTitle(String title) { - synchronized (this.m_page) { - if (this.m_printing) { + void setPageTitle( String title ) + { + synchronized( this.m_page ) + { + if( this.m_printing ) + { this.m_pageTitle = title; } } } - private boolean canInputPage() { - ItemStack inkStack = this.m_inventory.get(0); - return !inkStack.isEmpty() && isInk(inkStack) && this.getPaperLevel() > 0; + private boolean canInputPage() + { + ItemStack inkStack = this.m_inventory.get( 0 ); + return !inkStack.isEmpty() && isInk( inkStack ) && this.getPaperLevel() > 0; } - private boolean inputPage() { - ItemStack inkStack = this.m_inventory.get(0); + private boolean inputPage() + { + ItemStack inkStack = this.m_inventory.get( 0 ); DyeColor dye = ColourUtils.getStackColour( inkStack ); if( dye == null ) return false; - for (int i = 1; i < 7; i++) { - ItemStack paperStack = this.m_inventory.get(i); - if (paperStack.isEmpty() || !isPaper(paperStack)) { + for( int i = 1; i < 7; i++ ) + { + ItemStack paperStack = this.m_inventory.get( i ); + if( paperStack.isEmpty() || !isPaper( paperStack ) ) + { continue; } @@ -393,28 +462,34 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent m_page.setTextColour( dye.getId() ); this.m_page.clear(); - if (paperStack.getItem() instanceof ItemPrintout) { - this.m_pageTitle = ItemPrintout.getTitle(paperStack); - String[] text = ItemPrintout.getText(paperStack); - String[] textColour = ItemPrintout.getColours(paperStack); - for (int y = 0; y < this.m_page.getHeight(); y++) { - this.m_page.setLine(y, text[y], textColour[y], ""); + if( paperStack.getItem() instanceof ItemPrintout ) + { + this.m_pageTitle = ItemPrintout.getTitle( paperStack ); + String[] text = ItemPrintout.getText( paperStack ); + String[] textColour = ItemPrintout.getColours( paperStack ); + for( int y = 0; y < this.m_page.getHeight(); y++ ) + { + this.m_page.setLine( y, text[y], textColour[y], "" ); } - } else { + } + else + { this.m_pageTitle = ""; } - this.m_page.setCursorPos(0, 0); + this.m_page.setCursorPos( 0, 0 ); // Decrement ink - inkStack.decrement(1); - if (inkStack.isEmpty()) { - this.m_inventory.set(0, ItemStack.EMPTY); + inkStack.decrement( 1 ); + if( inkStack.isEmpty() ) + { + this.m_inventory.set( 0, ItemStack.EMPTY ); } // Decrement paper - paperStack.decrement(1); - if (paperStack.isEmpty()) { - this.m_inventory.set(i, ItemStack.EMPTY); + paperStack.decrement( 1 ); + if( paperStack.isEmpty() ) + { + this.m_inventory.set( i, ItemStack.EMPTY ); this.updateBlockState(); } @@ -427,30 +502,35 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Nonnull @Override - public Text getName() { - return this.customName != null ? this.customName : new TranslatableText(this.getCachedState().getBlock() - .getTranslationKey()); + public Text getName() + { + return this.customName != null ? this.customName : new TranslatableText( this.getCachedState().getBlock() + .getTranslationKey() ); } @Override - public boolean hasCustomName() { + public boolean hasCustomName() + { return this.customName != null; } @Override - public Text getDisplayName() { + public Text getDisplayName() + { return Nameable.super.getDisplayName(); } @Nullable @Override - public Text getCustomName() { + public Text getCustomName() + { return this.customName; } @Nonnull @Override - public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) { - return new ContainerPrinter(id, inventory, this); + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) + { + return new ContainerPrinter( id, inventory, this ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java index 9b076a19e..366d82d76 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java @@ -6,11 +6,8 @@ package dan200.computercraft.shared.peripheral.speaker; -import javax.annotation.Nullable; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.item.ItemPlacementContext; @@ -19,25 +16,31 @@ import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.Properties; import net.minecraft.util.math.Direction; -public class BlockSpeaker extends BlockGeneric { +import javax.annotation.Nullable; + +public class BlockSpeaker extends BlockGeneric +{ private static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - public BlockSpeaker(Settings settings) { - super(settings, ComputerCraftRegistry.ModTiles.SPEAKER); - this.setDefaultState(this.getStateManager().getDefaultState() - .with(FACING, Direction.NORTH)); + public BlockSpeaker( Settings settings ) + { + super( settings, ComputerCraftRegistry.ModTiles.SPEAKER ); + this.setDefaultState( this.getStateManager().getDefaultState() + .with( FACING, Direction.NORTH ) ); } @Nullable @Override - public BlockState getPlacementState(ItemPlacementContext placement) { - return this.getDefaultState().with(FACING, - placement.getPlayerFacing() - .getOpposite()); + public BlockState getPlacementState( ItemPlacementContext placement ) + { + return this.getDefaultState().with( FACING, + placement.getPlayerFacing() + .getOpposite() ); } @Override - protected void appendProperties(StateManager.Builder properties) { - properties.add(FACING); + protected void appendProperties( StateManager.Builder properties ) + { + properties.add( FACING ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java index c39a750a5..2e9ffe3b5 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java @@ -6,20 +6,12 @@ package dan200.computercraft.shared.peripheral.speaker; -import static dan200.computercraft.api.lua.LuaValues.checkFinite; - -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.fabric.mixin.SoundEventAccess; - import net.minecraft.block.enums.Instrument; import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; import net.minecraft.server.MinecraftServer; @@ -29,28 +21,38 @@ import net.minecraft.util.InvalidIdentifierException; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import javax.annotation.Nonnull; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +import static dan200.computercraft.api.lua.LuaValues.checkFinite; + /** * Speakers allow playing notes and other sounds. * * @cc.module speaker */ -public abstract class SpeakerPeripheral implements IPeripheral { +public abstract class SpeakerPeripheral implements IPeripheral +{ private final AtomicInteger m_notesThisTick = new AtomicInteger(); private long m_clock = 0; private long m_lastPlayTime = 0; - public void update() { + public void update() + { this.m_clock++; - this.m_notesThisTick.set(0); + this.m_notesThisTick.set( 0 ); } - public boolean madeSound(long ticks) { + public boolean madeSound( long ticks ) + { return this.m_clock - this.m_lastPlayTime <= ticks; } @Nonnull @Override - public String getType() { + public String getType() + { return "speaker"; } @@ -61,29 +63,35 @@ public abstract class SpeakerPeripheral implements IPeripheral { * minecraft:block.note_block.harp}) with an optional volume and speed multiplier, and plays it through the speaker. * * @param context The Lua context - * @param name The name of the sound to play. + * @param name The name of the sound to play. * @param volumeA The volume to play the sound at, from 0.0 to 3.0. Defaults to 1.0. - * @param pitchA The speed to play the sound at, from 0.5 to 2.0. Defaults to 1.0. + * @param pitchA The speed to play the sound at, from 0.5 to 2.0. Defaults to 1.0. * @return Whether the sound could be played. * @throws LuaException If the sound name couldn't be decoded. */ @LuaFunction - public final boolean playSound(ILuaContext context, String name, Optional volumeA, Optional pitchA) throws LuaException { - float volume = (float) checkFinite(1, volumeA.orElse(1.0)); - float pitch = (float) checkFinite(2, pitchA.orElse(1.0)); + public final boolean playSound( ILuaContext context, String name, Optional volumeA, Optional pitchA ) throws LuaException + { + float volume = (float) checkFinite( 1, volumeA.orElse( 1.0 ) ); + float pitch = (float) checkFinite( 2, pitchA.orElse( 1.0 ) ); Identifier identifier; - try { - identifier = new Identifier(name); - } catch (InvalidIdentifierException e) { - throw new LuaException("Malformed sound name '" + name + "' "); + try + { + identifier = new Identifier( name ); + } + catch( InvalidIdentifierException e ) + { + throw new LuaException( "Malformed sound name '" + name + "' " ); } - return this.playSound(context, identifier, volume, pitch, false); + return this.playSound( context, identifier, volume, pitch, false ); } - private synchronized boolean playSound(ILuaContext context, Identifier name, float volume, float pitch, boolean isNote) throws LuaException { - if (this.m_clock - this.m_lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS && (!isNote || this.m_clock - this.m_lastPlayTime != 0 || this.m_notesThisTick.get() >= ComputerCraft.maxNotesPerTick)) { + private synchronized boolean playSound( ILuaContext context, Identifier name, float volume, float pitch, boolean isNote ) throws LuaException + { + if( this.m_clock - this.m_lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS && (!isNote || this.m_clock - this.m_lastPlayTime != 0 || this.m_notesThisTick.get() >= ComputerCraft.maxNotesPerTick) ) + { // Rate limiting occurs when we've already played a sound within the last tick, or we've // played more notes than allowable within the current tick. return false; @@ -92,23 +100,24 @@ public abstract class SpeakerPeripheral implements IPeripheral { World world = this.getWorld(); Vec3d pos = this.getPosition(); - context.issueMainThreadTask(() -> { + context.issueMainThreadTask( () -> { MinecraftServer server = world.getServer(); - if (server == null) { + if( server == null ) + { return null; } - float adjVolume = Math.min(volume, 3.0f); + float adjVolume = Math.min( volume, 3.0f ); server.getPlayerManager() - .sendToAround(null, + .sendToAround( null, pos.x, pos.y, pos.z, adjVolume > 1.0f ? 16 * adjVolume : 16.0, world.getRegistryKey(), - new PlaySoundIdS2CPacket(name, SoundCategory.RECORDS, pos, adjVolume, pitch)); + new PlaySoundIdS2CPacket( name, SoundCategory.RECORDS, pos, adjVolume, pitch ) ); return null; - }); + } ); this.m_lastPlayTime = this.m_clock; return true; @@ -127,38 +136,43 @@ public abstract class SpeakerPeripheral implements IPeripheral { * and 6 and 18 map to C. * * @param context The Lua context - * @param name The name of the note to play. + * @param name The name of the note to play. * @param volumeA The volume to play the note at, from 0.0 to 3.0. Defaults to 1.0. - * @param pitchA The pitch to play the note at in semitones, from 0 to 24. Defaults to 12. + * @param pitchA The pitch to play the note at in semitones, from 0 to 24. Defaults to 12. * @return Whether the note could be played. * @throws LuaException If the instrument doesn't exist. */ @LuaFunction - public final synchronized boolean playNote(ILuaContext context, String name, Optional volumeA, Optional pitchA) throws LuaException { - float volume = (float) checkFinite(1, volumeA.orElse(1.0)); - float pitch = (float) checkFinite(2, pitchA.orElse(1.0)); + public final synchronized boolean playNote( ILuaContext context, String name, Optional volumeA, Optional pitchA ) throws LuaException + { + float volume = (float) checkFinite( 1, volumeA.orElse( 1.0 ) ); + float pitch = (float) checkFinite( 2, pitchA.orElse( 1.0 ) ); Instrument instrument = null; - for (Instrument testInstrument : Instrument.values()) { - if (testInstrument.asString() - .equalsIgnoreCase(name)) { + for( Instrument testInstrument : Instrument.values() ) + { + if( testInstrument.asString() + .equalsIgnoreCase( name ) ) + { instrument = testInstrument; break; } } // Check if the note exists - if (instrument == null) { - throw new LuaException("Invalid instrument, \"" + name + "\"!"); + if( instrument == null ) + { + throw new LuaException( "Invalid instrument, \"" + name + "\"!" ); } // If the resource location for note block notes changes, this method call will need to be updated - boolean success = this.playSound(context, - ((SoundEventAccess)instrument.getSound()).getId(), + boolean success = this.playSound( context, + ((SoundEventAccess) instrument.getSound()).getId(), volume, - (float) Math.pow(2.0, (pitch - 12.0) / 12.0), - true); - if (success) { + (float) Math.pow( 2.0, (pitch - 12.0) / 12.0 ), + true ); + if( success ) + { this.m_notesThisTick.incrementAndGet(); } return success; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java index 5c5578b7c..9b0bda5a3 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java @@ -6,13 +6,9 @@ package dan200.computercraft.shared.peripheral.speaker; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheralTile; import dan200.computercraft.shared.common.TileGeneric; - import net.minecraft.block.entity.BlockEntityType; import net.minecraft.util.Tickable; import net.minecraft.util.math.BlockPos; @@ -20,47 +16,59 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class TileSpeaker extends TileGeneric implements Tickable, IPeripheralTile { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class TileSpeaker extends TileGeneric implements Tickable, IPeripheralTile +{ public static final int MIN_TICKS_BETWEEN_SOUNDS = 1; private final SpeakerPeripheral peripheral; - public TileSpeaker(BlockEntityType type) { - super(type); - this.peripheral = new Peripheral(this); + public TileSpeaker( BlockEntityType type ) + { + super( type ); + this.peripheral = new Peripheral( this ); } @Override - public void tick() { + public void tick() + { this.peripheral.update(); } @Nonnull @Override - public IPeripheral getPeripheral(Direction side) { + public IPeripheral getPeripheral( Direction side ) + { return this.peripheral; } - private static final class Peripheral extends SpeakerPeripheral { + private static final class Peripheral extends SpeakerPeripheral + { private final TileSpeaker speaker; - private Peripheral(TileSpeaker speaker) { + private Peripheral( TileSpeaker speaker ) + { this.speaker = speaker; } @Override - public World getWorld() { + public World getWorld() + { return this.speaker.getWorld(); } @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { BlockPos pos = this.speaker.getPos(); - return new Vec3d(pos.getX(), pos.getY(), pos.getZ()); + return new Vec3d( pos.getX(), pos.getY(), pos.getZ() ); } @Override - public boolean equals(@Nullable IPeripheral other) { + public boolean equals( @Nullable IPeripheral other ) + { return this == other || (other instanceof Peripheral && this.speaker == ((Peripheral) other).speaker); } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java index b2c3a8f36..55b9168b6 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java +++ b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java @@ -14,7 +14,6 @@ import dan200.computercraft.shared.pocket.core.PocketServerComputer; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; @@ -36,16 +35,19 @@ import net.minecraft.util.collection.DefaultedList; * * @cc.module pocket */ -public class PocketAPI implements ILuaAPI { +public class PocketAPI implements ILuaAPI +{ private final PocketServerComputer computer; - public PocketAPI(PocketServerComputer computer) { + public PocketAPI( PocketServerComputer computer ) + { this.computer = computer; } @Override - public String[] getNames() { - return new String[] {"pocket"}; + public String[] getNames() + { + return new String[] { "pocket" }; } /** @@ -57,10 +59,12 @@ public class PocketAPI implements ILuaAPI { * @cc.treturn boolean If an item was equipped. * @cc.treturn string|nil The reason an item was not equipped. */ - @LuaFunction (mainThread = true) - public final Object[] equipBack() { + @LuaFunction( mainThread = true ) + public final Object[] equipBack() + { Entity entity = this.computer.getEntity(); - if (!(entity instanceof PlayerEntity)) { + if( !(entity instanceof PlayerEntity) ) + { return new Object[] { false, "Cannot find player" @@ -72,11 +76,13 @@ public class PocketAPI implements ILuaAPI { // Attempt to find the upgrade, starting in the main segment, and then looking in the opposite // one. We start from the position the item is currently in and loop round to the start. - IPocketUpgrade newUpgrade = findUpgrade(inventory.main, inventory.selectedSlot, previousUpgrade); - if (newUpgrade == null) { - newUpgrade = findUpgrade(inventory.offHand, 0, previousUpgrade); + IPocketUpgrade newUpgrade = findUpgrade( inventory.main, inventory.selectedSlot, previousUpgrade ); + if( newUpgrade == null ) + { + newUpgrade = findUpgrade( inventory.offHand, 0, previousUpgrade ); } - if (newUpgrade == null) { + if( newUpgrade == null ) + { return new Object[] { false, "Cannot find a valid upgrade" @@ -84,33 +90,40 @@ public class PocketAPI implements ILuaAPI { } // Remove the current upgrade - if (previousUpgrade != null) { + if( previousUpgrade != null ) + { ItemStack stack = previousUpgrade.getCraftingItem(); - if (!stack.isEmpty()) { - stack = InventoryUtil.storeItems(stack, ItemStorage.wrap(inventory), inventory.selectedSlot); - if (!stack.isEmpty()) { - WorldUtil.dropItemStack(stack, player.getEntityWorld(), player.getPos()); + if( !stack.isEmpty() ) + { + stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot ); + if( !stack.isEmpty() ) + { + WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() ); } } } // Set the new upgrade - this.computer.setUpgrade(newUpgrade); + this.computer.setUpgrade( newUpgrade ); - return new Object[] {true}; + return new Object[] { true }; } - private static IPocketUpgrade findUpgrade(DefaultedList inv, int start, IPocketUpgrade previous) { - for (int i = 0; i < inv.size(); i++) { - ItemStack invStack = inv.get((i + start) % inv.size()); - if (!invStack.isEmpty()) { - IPocketUpgrade newUpgrade = PocketUpgrades.get(invStack); + private static IPocketUpgrade findUpgrade( DefaultedList inv, int start, IPocketUpgrade previous ) + { + for( int i = 0; i < inv.size(); i++ ) + { + ItemStack invStack = inv.get( (i + start) % inv.size() ); + if( !invStack.isEmpty() ) + { + IPocketUpgrade newUpgrade = PocketUpgrades.get( invStack ); - if (newUpgrade != null && newUpgrade != previous) { + if( newUpgrade != null && newUpgrade != previous ) + { // Consume an item from this stack and exit the loop invStack = invStack.copy(); - invStack.decrement(1); - inv.set((i + start) % inv.size(), invStack.isEmpty() ? ItemStack.EMPTY : invStack); + invStack.decrement( 1 ); + inv.set( (i + start) % inv.size(), invStack.isEmpty() ? ItemStack.EMPTY : invStack ); return newUpgrade; } @@ -127,10 +140,12 @@ public class PocketAPI implements ILuaAPI { * @cc.treturn boolean If the upgrade was unequipped. * @cc.treturn string|nil The reason an upgrade was not unequipped. */ - @LuaFunction (mainThread = true) - public final Object[] unequipBack() { + @LuaFunction( mainThread = true ) + public final Object[] unequipBack() + { Entity entity = this.computer.getEntity(); - if (!(entity instanceof PlayerEntity)) { + if( !(entity instanceof PlayerEntity) ) + { return new Object[] { false, "Cannot find player" @@ -140,23 +155,26 @@ public class PocketAPI implements ILuaAPI { PlayerInventory inventory = player.inventory; IPocketUpgrade previousUpgrade = this.computer.getUpgrade(); - if (previousUpgrade == null) { + if( previousUpgrade == null ) + { return new Object[] { false, "Nothing to unequip" }; } - this.computer.setUpgrade(null); + this.computer.setUpgrade( null ); ItemStack stack = previousUpgrade.getCraftingItem(); - if (!stack.isEmpty()) { - stack = InventoryUtil.storeItems(stack, ItemStorage.wrap(inventory), inventory.selectedSlot); - if (stack.isEmpty()) { - WorldUtil.dropItemStack(stack, player.getEntityWorld(), player.getPos()); + if( !stack.isEmpty() ) + { + stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot ); + if( stack.isEmpty() ) + { + WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() ); } } - return new Object[] {true}; + return new Object[] { true }; } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java index c6eeafde3..bc28daa9a 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java @@ -6,14 +6,6 @@ package dan200.computercraft.shared.pocket.core; -import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT; - -import java.util.Collections; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.pocket.IPocketAccess; @@ -25,7 +17,6 @@ import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.util.NBTUtil; - import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; @@ -36,91 +27,121 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.world.World; -public class PocketServerComputer extends ServerComputer implements IPocketAccess { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.Map; + +import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT; + +public class PocketServerComputer extends ServerComputer implements IPocketAccess +{ private IPocketUpgrade m_upgrade; private Entity m_entity; private ItemStack m_stack; - public PocketServerComputer(World world, int computerID, String label, int instanceID, ComputerFamily family) { - super(world, computerID, label, instanceID, family, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight); + public PocketServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family ) + { + super( world, computerID, label, instanceID, family, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ); } @Nullable @Override - public Entity getEntity() { + public Entity getEntity() + { Entity entity = this.m_entity; - if (entity == null || this.m_stack == null || !entity.isAlive()) { + if( entity == null || this.m_stack == null || !entity.isAlive() ) + { return null; } - if (entity instanceof PlayerEntity) { + if( entity instanceof PlayerEntity ) + { PlayerInventory inventory = ((PlayerEntity) entity).inventory; - return inventory.main.contains(this.m_stack) || inventory.offHand.contains(this.m_stack) ? entity : null; - } else if (entity instanceof LivingEntity) { + return inventory.main.contains( this.m_stack ) || inventory.offHand.contains( this.m_stack ) ? entity : null; + } + else if( entity instanceof LivingEntity ) + { LivingEntity living = (LivingEntity) entity; return living.getMainHandStack() == this.m_stack || living.getOffHandStack() == this.m_stack ? entity : null; - } else { + } + else + { return null; } } @Override - public int getColour() { - return IColouredItem.getColourBasic(this.m_stack); + public int getColour() + { + return IColouredItem.getColourBasic( this.m_stack ); } @Override - public void setColour(int colour) { - IColouredItem.setColourBasic(this.m_stack, colour); + public void setColour( int colour ) + { + IColouredItem.setColourBasic( this.m_stack, colour ); this.updateUpgradeNBTData(); } @Override - public int getLight() { + public int getLight() + { CompoundTag tag = this.getUserData(); - return tag.contains(NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC) ? tag.getInt(NBT_LIGHT) : -1; + return tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_LIGHT ) : -1; } @Override - public void setLight(int colour) { + public void setLight( int colour ) + { CompoundTag tag = this.getUserData(); - if (colour >= 0 && colour <= 0xFFFFFF) { - if (!tag.contains(NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC) || tag.getInt(NBT_LIGHT) != colour) { - tag.putInt(NBT_LIGHT, colour); + if( colour >= 0 && colour <= 0xFFFFFF ) + { + if( !tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) || tag.getInt( NBT_LIGHT ) != colour ) + { + tag.putInt( NBT_LIGHT, colour ); this.updateUserData(); } - } else if (tag.contains(NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC)) { - tag.remove(NBT_LIGHT); + } + else if( tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) ) + { + tag.remove( NBT_LIGHT ); this.updateUserData(); } } @Nonnull @Override - public CompoundTag getUpgradeNBTData() { - return ItemPocketComputer.getUpgradeInfo(this.m_stack); + public CompoundTag getUpgradeNBTData() + { + return ItemPocketComputer.getUpgradeInfo( this.m_stack ); } @Override - public void updateUpgradeNBTData() { - if (this.m_entity instanceof PlayerEntity) { + public void updateUpgradeNBTData() + { + if( this.m_entity instanceof PlayerEntity ) + { ((PlayerEntity) this.m_entity).inventory.markDirty(); } } @Override - public void invalidatePeripheral() { - IPeripheral peripheral = this.m_upgrade == null ? null : this.m_upgrade.createPeripheral(this); - this.setPeripheral(ComputerSide.BACK, peripheral); + public void invalidatePeripheral() + { + IPeripheral peripheral = this.m_upgrade == null ? null : this.m_upgrade.createPeripheral( this ); + this.setPeripheral( ComputerSide.BACK, peripheral ); } @Nonnull @Override - public Map getUpgrades() { - return this.m_upgrade == null ? Collections.emptyMap() : Collections.singletonMap(this.m_upgrade.getUpgradeID(), this.getPeripheral(ComputerSide.BACK)); + public Map getUpgrades() + { + return this.m_upgrade == null ? Collections.emptyMap() : Collections.singletonMap( this.m_upgrade.getUpgradeID(), this.getPeripheral( ComputerSide.BACK ) ); } - public IPocketUpgrade getUpgrade() { + public IPocketUpgrade getUpgrade() + { return this.m_upgrade; } @@ -131,48 +152,58 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces * * @param upgrade The new upgrade to set it to, may be {@code null}. */ - public void setUpgrade(IPocketUpgrade upgrade) { - if (this.m_upgrade == upgrade) { + public void setUpgrade( IPocketUpgrade upgrade ) + { + if( this.m_upgrade == upgrade ) + { return; } - synchronized (this) { - ItemPocketComputer.setUpgrade(this.m_stack, upgrade); + synchronized( this ) + { + ItemPocketComputer.setUpgrade( this.m_stack, upgrade ); this.updateUpgradeNBTData(); this.m_upgrade = upgrade; this.invalidatePeripheral(); } } - public synchronized void updateValues(Entity entity, @Nonnull ItemStack stack, IPocketUpgrade upgrade) { - if (entity != null) { - this.setWorld(entity.getEntityWorld()); - this.setPosition(entity.getBlockPos()); + public synchronized void updateValues( Entity entity, @Nonnull ItemStack stack, IPocketUpgrade upgrade ) + { + if( entity != null ) + { + this.setWorld( entity.getEntityWorld() ); + this.setPosition( entity.getBlockPos() ); } // If a new entity has picked it up then rebroadcast the terminal to them - if (entity != this.m_entity && entity instanceof ServerPlayerEntity) { + if( entity != this.m_entity && entity instanceof ServerPlayerEntity ) + { this.markTerminalChanged(); } this.m_entity = entity; this.m_stack = stack; - if (this.m_upgrade != upgrade) { + if( this.m_upgrade != upgrade ) + { this.m_upgrade = upgrade; this.invalidatePeripheral(); } } @Override - public void broadcastState(boolean force) { - super.broadcastState(force); + public void broadcastState( boolean force ) + { + super.broadcastState( force ); - if ((this.hasTerminalChanged() || force) && this.m_entity instanceof ServerPlayerEntity) { + if( (this.hasTerminalChanged() || force) && this.m_entity instanceof ServerPlayerEntity ) + { // Broadcast the state to the current entity if they're not already interacting with it. ServerPlayerEntity player = (ServerPlayerEntity) this.m_entity; - if (player.networkHandler != null && !this.isInteracting(player)) { - NetworkHandler.sendToPlayer(player, this.createTerminalPacket()); + if( player.networkHandler != null && !this.isInteracting( player ) ) + { + NetworkHandler.sendToPlayer( player, this.createTerminalPacket() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java index c0a136e47..9a41f3a5a 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java @@ -6,14 +6,11 @@ package dan200.computercraft.shared.pocket.inventory; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; - +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; @@ -24,27 +21,33 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Hand; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; -public final class ContainerPocketComputer extends ContainerComputerBase { - private ContainerPocketComputer(int id, ServerComputer computer, ItemPocketComputer item, Hand hand) { - super(ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, p -> { - ItemStack stack = p.getStackInHand(hand); - return stack.getItem() == item && ItemPocketComputer.getServerComputer(stack) == computer; - }, computer, item.getFamily()); +public final class ContainerPocketComputer extends ContainerComputerBase +{ + private ContainerPocketComputer( int id, ServerComputer computer, ItemPocketComputer item, Hand hand ) + { + super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, p -> { + ItemStack stack = p.getStackInHand( hand ); + return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer; + }, computer, item.getFamily() ); } - public ContainerPocketComputer(int id, PlayerInventory player, PacketByteBuf packetByteBuf) { - super(ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, player, packetByteBuf); + public ContainerPocketComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf ) + { + super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, player, packetByteBuf ); } - public static class Factory implements NamedScreenHandlerFactory, ExtendedScreenHandlerFactory { + public static class Factory implements NamedScreenHandlerFactory, ExtendedScreenHandlerFactory + { private final ServerComputer computer; private final Text name; private final ItemPocketComputer item; private final Hand hand; - public Factory(ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand) { + public Factory( ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand ) + { this.computer = computer; this.name = stack.getName(); this.item = item; @@ -54,20 +57,23 @@ public final class ContainerPocketComputer extends ContainerComputerBase { @Nonnull @Override - public Text getDisplayName() { + public Text getDisplayName() + { return this.name; } @Nullable @Override - public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity) { - return new ContainerPocketComputer(id, this.computer, this.item, this.hand); + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity ) + { + return new ContainerPocketComputer( id, this.computer, this.item, this.hand ); } @Override - public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) { - packetByteBuf.writeInt(this.computer.getInstanceID()); - packetByteBuf.writeEnumConstant(this.computer.getFamily()); + public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf ) + { + packetByteBuf.writeInt( this.computer.getInstanceID() ); + packetByteBuf.writeEnumConstant( this.computer.getFamily() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java index b3c4ad312..7eda82a58 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.pocket.items; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.base.Objects; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; @@ -29,7 +24,8 @@ import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.pocket.apis.PocketAPI; import dan200.computercraft.shared.pocket.core.PocketServerComputer; import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; @@ -48,10 +44,12 @@ import net.minecraft.util.TypedActionResult; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; -public class ItemPocketComputer extends Item implements IComputerItem, IMedia, IColouredItem { +public class ItemPocketComputer extends Item implements IComputerItem, IMedia, IColouredItem +{ public static final String NBT_LIGHT = "Light"; private static final String NBT_UPGRADE = "Upgrade"; private static final String NBT_UPGRADE_INFO = "UpgradeInfo"; @@ -60,58 +58,70 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I private final ComputerFamily family; - public ItemPocketComputer(Settings settings, ComputerFamily family) { - super(settings); + public ItemPocketComputer( Settings settings, ComputerFamily family ) + { + super( settings ); this.family = family; } - public static ServerComputer getServerComputer(@Nonnull ItemStack stack) { + public static ServerComputer getServerComputer( @Nonnull ItemStack stack ) + { int session = getSessionID( stack ); if( session != ComputerCraft.serverComputerRegistry.getSessionID() ) return null; - int instanceID = getInstanceID(stack); - return instanceID >= 0 ? ComputerCraft.serverComputerRegistry.get(instanceID) : null; + int instanceID = getInstanceID( stack ); + return instanceID >= 0 ? ComputerCraft.serverComputerRegistry.get( instanceID ) : null; } - @Environment (EnvType.CLIENT) - public static ComputerState getState(@Nonnull ItemStack stack) { - ClientComputer computer = getClientComputer(stack); + @Environment( EnvType.CLIENT ) + public static ComputerState getState( @Nonnull ItemStack stack ) + { + ClientComputer computer = getClientComputer( stack ); return computer == null ? ComputerState.OFF : computer.getState(); } - private static ClientComputer getClientComputer(@Nonnull ItemStack stack) { - int instanceID = getInstanceID(stack); - return instanceID >= 0 ? ComputerCraft.clientComputerRegistry.get(instanceID) : null; + private static ClientComputer getClientComputer( @Nonnull ItemStack stack ) + { + int instanceID = getInstanceID( stack ); + return instanceID >= 0 ? ComputerCraft.clientComputerRegistry.get( instanceID ) : null; } - @Environment (EnvType.CLIENT) - public static int getLightState(@Nonnull ItemStack stack) { - ClientComputer computer = getClientComputer(stack); - if (computer != null && computer.isOn()) { + @Environment( EnvType.CLIENT ) + public static int getLightState( @Nonnull ItemStack stack ) + { + ClientComputer computer = getClientComputer( stack ); + if( computer != null && computer.isOn() ) + { CompoundTag computerNBT = computer.getUserData(); - if (computerNBT != null && computerNBT.contains(NBT_LIGHT)) { - return computerNBT.getInt(NBT_LIGHT); + if( computerNBT != null && computerNBT.contains( NBT_LIGHT ) ) + { + return computerNBT.getInt( NBT_LIGHT ); } } return -1; } - public static void setUpgrade(@Nonnull ItemStack stack, IPocketUpgrade upgrade) { + public static void setUpgrade( @Nonnull ItemStack stack, IPocketUpgrade upgrade ) + { CompoundTag compound = stack.getOrCreateTag(); - if (upgrade == null) { - compound.remove(NBT_UPGRADE); - } else { - compound.putString(NBT_UPGRADE, - upgrade.getUpgradeID() - .toString()); + if( upgrade == null ) + { + compound.remove( NBT_UPGRADE ); + } + else + { + compound.putString( NBT_UPGRADE, + upgrade.getUpgradeID() + .toString() ); } - compound.remove(NBT_UPGRADE_INFO); + compound.remove( NBT_UPGRADE_INFO ); } - public static CompoundTag getUpgradeInfo(@Nonnull ItemStack stack) { - return stack.getOrCreateSubTag(NBT_UPGRADE_INFO); + public static CompoundTag getUpgradeInfo( @Nonnull ItemStack stack ) + { + return stack.getOrCreateSubTag( NBT_UPGRADE_INFO ); } // @Nullable @@ -132,239 +142,295 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I @Nonnull @Override - public TypedActionResult use(World world, PlayerEntity player, @Nonnull Hand hand) { - ItemStack stack = player.getStackInHand(hand); - if (!world.isClient) { - PocketServerComputer computer = this.createServerComputer(world, player.inventory, player, stack); + public TypedActionResult use( World world, PlayerEntity player, @Nonnull Hand hand ) + { + ItemStack stack = player.getStackInHand( hand ); + if( !world.isClient ) + { + PocketServerComputer computer = this.createServerComputer( world, player.inventory, player, stack ); boolean stop = false; - if (computer != null) { + if( computer != null ) + { computer.turnOn(); - IPocketUpgrade upgrade = getUpgrade(stack); - if (upgrade != null) { - computer.updateValues(player, stack, upgrade); - stop = upgrade.onRightClick(world, computer, computer.getPeripheral(ComputerSide.BACK)); + IPocketUpgrade upgrade = getUpgrade( stack ); + if( upgrade != null ) + { + computer.updateValues( player, stack, upgrade ); + stop = upgrade.onRightClick( world, computer, computer.getPeripheral( ComputerSide.BACK ) ); } } - if (!stop && computer != null) { - computer.sendTerminalState(player); - new ComputerContainerData(computer).open(player, new ContainerPocketComputer.Factory(computer, stack, this, hand)); + if( !stop && computer != null ) + { + computer.sendTerminalState( player ); + new ComputerContainerData( computer ).open( player, new ContainerPocketComputer.Factory( computer, stack, this, hand ) ); } } - return new TypedActionResult<>(ActionResult.SUCCESS, stack); + return new TypedActionResult<>( ActionResult.SUCCESS, stack ); } @Override - public void inventoryTick(@Nonnull ItemStack stack, World world, @Nonnull Entity entity, int slotNum, boolean selected) { - if (!world.isClient) { + public void inventoryTick( @Nonnull ItemStack stack, World world, @Nonnull Entity entity, int slotNum, boolean selected ) + { + if( !world.isClient ) + { // Server side Inventory inventory = entity instanceof PlayerEntity ? ((PlayerEntity) entity).inventory : null; - PocketServerComputer computer = this.createServerComputer(world, inventory, entity, stack); - if (computer != null) { - IPocketUpgrade upgrade = getUpgrade(stack); + PocketServerComputer computer = this.createServerComputer( world, inventory, entity, stack ); + if( computer != null ) + { + IPocketUpgrade upgrade = getUpgrade( stack ); // Ping computer computer.keepAlive(); - computer.setWorld(world); - computer.updateValues(entity, stack, upgrade); + computer.setWorld( world ); + computer.updateValues( entity, stack, upgrade ); // Sync ID int id = computer.getID(); - if (id != this.getComputerID(stack)) { - setComputerID(stack, id); - if (inventory != null) { + if( id != this.getComputerID( stack ) ) + { + setComputerID( stack, id ); + if( inventory != null ) + { inventory.markDirty(); } } // Sync label String label = computer.getLabel(); - if (!Objects.equal(label, this.getLabel(stack))) { - this.setLabel(stack, label); - if (inventory != null) { + if( !Objects.equal( label, this.getLabel( stack ) ) ) + { + this.setLabel( stack, label ); + if( inventory != null ) + { inventory.markDirty(); } } // Update pocket upgrade - if (upgrade != null) { - upgrade.update(computer, computer.getPeripheral(ComputerSide.BACK)); + if( upgrade != null ) + { + upgrade.update( computer, computer.getPeripheral( ComputerSide.BACK ) ); } } - } else { + } + else + { // Client side - createClientComputer(stack); + createClientComputer( stack ); } } @Override - public void appendTooltip(@Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, TooltipContext flag) { - if (flag.isAdvanced() || this.getLabel(stack) == null) { - int id = this.getComputerID(stack); - if (id >= 0) { - list.add(new TranslatableText("gui.computercraft.tooltip.computer_id", id).formatted(Formatting.GRAY)); + public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, TooltipContext flag ) + { + if( flag.isAdvanced() || this.getLabel( stack ) == null ) + { + int id = this.getComputerID( stack ); + if( id >= 0 ) + { + list.add( new TranslatableText( "gui.computercraft.tooltip.computer_id", id ).formatted( Formatting.GRAY ) ); } } } @Nonnull @Override - public Text getName(@Nonnull ItemStack stack) { - String baseString = this.getTranslationKey(stack); - IPocketUpgrade upgrade = getUpgrade(stack); - if (upgrade != null) { - return new TranslatableText(baseString + ".upgraded", new TranslatableText(upgrade.getUnlocalisedAdjective())); - } else { - return super.getName(stack); + public Text getName( @Nonnull ItemStack stack ) + { + String baseString = this.getTranslationKey( stack ); + IPocketUpgrade upgrade = getUpgrade( stack ); + if( upgrade != null ) + { + return new TranslatableText( baseString + ".upgraded", new TranslatableText( upgrade.getUnlocalisedAdjective() ) ); + } + else + { + return super.getName( stack ); } } // IComputerItem implementation @Override - public void appendStacks(@Nonnull ItemGroup group, @Nonnull DefaultedList stacks) { - if (!this.isIn(group)) { + public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList stacks ) + { + if( !this.isIn( group ) ) + { return; } - stacks.add(this.create(-1, null, -1, null)); - for (IPocketUpgrade upgrade : PocketUpgrades.getVanillaUpgrades()) { - stacks.add(this.create(-1, null, -1, upgrade)); + stacks.add( this.create( -1, null, -1, null ) ); + for( IPocketUpgrade upgrade : PocketUpgrades.getVanillaUpgrades() ) + { + stacks.add( this.create( -1, null, -1, upgrade ) ); } } - public ItemStack create(int id, String label, int colour, IPocketUpgrade upgrade) { - ItemStack result = new ItemStack(this); - if (id >= 0) { + public ItemStack create( int id, String label, int colour, IPocketUpgrade upgrade ) + { + ItemStack result = new ItemStack( this ); + if( id >= 0 ) + { result.getOrCreateTag() - .putInt(NBT_ID, id); + .putInt( NBT_ID, id ); } - if (label != null) { - result.setCustomName(new LiteralText(label)); + if( label != null ) + { + result.setCustomName( new LiteralText( label ) ); } - if (upgrade != null) { + if( upgrade != null ) + { result.getOrCreateTag() - .putString(NBT_UPGRADE, - upgrade.getUpgradeID() - .toString()); + .putString( NBT_UPGRADE, + upgrade.getUpgradeID() + .toString() ); } - if (colour != -1) { + if( colour != -1 ) + { result.getOrCreateTag() - .putInt(NBT_COLOUR, colour); + .putInt( NBT_COLOUR, colour ); } return result; } - public PocketServerComputer createServerComputer(final World world, Inventory inventory, Entity entity, @Nonnull ItemStack stack) { - if (world.isClient) { + public PocketServerComputer createServerComputer( final World world, Inventory inventory, Entity entity, @Nonnull ItemStack stack ) + { + if( world.isClient ) + { return null; } PocketServerComputer computer; - int instanceID = getInstanceID(stack); - int sessionID = getSessionID(stack); + int instanceID = getInstanceID( stack ); + int sessionID = getSessionID( stack ); int correctSessionID = ComputerCraft.serverComputerRegistry.getSessionID(); - if (instanceID >= 0 && sessionID == correctSessionID && ComputerCraft.serverComputerRegistry.contains(instanceID)) { - computer = (PocketServerComputer) ComputerCraft.serverComputerRegistry.get(instanceID); - } else { - if (instanceID < 0 || sessionID != correctSessionID) { + if( instanceID >= 0 && sessionID == correctSessionID && ComputerCraft.serverComputerRegistry.contains( instanceID ) ) + { + computer = (PocketServerComputer) ComputerCraft.serverComputerRegistry.get( instanceID ); + } + else + { + if( instanceID < 0 || sessionID != correctSessionID ) + { instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); - setInstanceID(stack, instanceID); - setSessionID(stack, correctSessionID); + setInstanceID( stack, instanceID ); + setSessionID( stack, correctSessionID ); } - int computerID = this.getComputerID(stack); - if (computerID < 0) { - computerID = ComputerCraftAPI.createUniqueNumberedSaveDir(world, "computer"); - setComputerID(stack, computerID); + int computerID = this.getComputerID( stack ); + if( computerID < 0 ) + { + computerID = ComputerCraftAPI.createUniqueNumberedSaveDir( world, "computer" ); + setComputerID( stack, computerID ); } - computer = new PocketServerComputer(world, computerID, this.getLabel(stack), instanceID, this.getFamily()); - computer.updateValues(entity, stack, getUpgrade(stack)); - computer.addAPI(new PocketAPI(computer)); - ComputerCraft.serverComputerRegistry.add(instanceID, computer); - if (inventory != null) { + computer = new PocketServerComputer( world, computerID, this.getLabel( stack ), instanceID, this.getFamily() ); + computer.updateValues( entity, stack, getUpgrade( stack ) ); + computer.addAPI( new PocketAPI( computer ) ); + ComputerCraft.serverComputerRegistry.add( instanceID, computer ); + if( inventory != null ) + { inventory.markDirty(); } } - computer.setWorld(world); + computer.setWorld( world ); return computer; } - public static IPocketUpgrade getUpgrade(@Nonnull ItemStack stack) { + public static IPocketUpgrade getUpgrade( @Nonnull ItemStack stack ) + { CompoundTag compound = stack.getTag(); - return compound != null && compound.contains(NBT_UPGRADE) ? PocketUpgrades.get(compound.getString(NBT_UPGRADE)) : null; + return compound != null && compound.contains( NBT_UPGRADE ) ? PocketUpgrades.get( compound.getString( NBT_UPGRADE ) ) : null; } // IMedia - private static void setComputerID(@Nonnull ItemStack stack, int computerID) { + private static void setComputerID( @Nonnull ItemStack stack, int computerID ) + { stack.getOrCreateTag() - .putInt(NBT_ID, computerID); + .putInt( NBT_ID, computerID ); } @Override - public String getLabel(@Nonnull ItemStack stack) { - return IComputerItem.super.getLabel(stack); + public String getLabel( @Nonnull ItemStack stack ) + { + return IComputerItem.super.getLabel( stack ); } @Override - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.family; } @Override - public ItemStack withFamily(@Nonnull ItemStack stack, @Nonnull ComputerFamily family) { - return PocketComputerItemFactory.create(this.getComputerID(stack), this.getLabel(stack), this.getColour(stack), family, getUpgrade(stack)); + public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) + { + return PocketComputerItemFactory.create( this.getComputerID( stack ), this.getLabel( stack ), this.getColour( stack ), family, getUpgrade( stack ) ); } @Override - public boolean setLabel(@Nonnull ItemStack stack, String label) { - if (label != null) { - stack.setCustomName(new LiteralText(label)); - } else { + public boolean setLabel( @Nonnull ItemStack stack, String label ) + { + if( label != null ) + { + stack.setCustomName( new LiteralText( label ) ); + } + else + { stack.removeCustomName(); } return true; } - public static ClientComputer createClientComputer(@Nonnull ItemStack stack) { - int instanceID = getInstanceID(stack); - if (instanceID >= 0) { - if (!ComputerCraft.clientComputerRegistry.contains(instanceID)) { - ComputerCraft.clientComputerRegistry.add(instanceID, new ClientComputer(instanceID)); + public static ClientComputer createClientComputer( @Nonnull ItemStack stack ) + { + int instanceID = getInstanceID( stack ); + if( instanceID >= 0 ) + { + if( !ComputerCraft.clientComputerRegistry.contains( instanceID ) ) + { + ComputerCraft.clientComputerRegistry.add( instanceID, new ClientComputer( instanceID ) ); } - return ComputerCraft.clientComputerRegistry.get(instanceID); + return ComputerCraft.clientComputerRegistry.get( instanceID ); } return null; } - private static int getInstanceID(@Nonnull ItemStack stack) { + private static int getInstanceID( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_INSTANCE) ? nbt.getInt(NBT_INSTANCE) : -1; + return nbt != null && nbt.contains( NBT_INSTANCE ) ? nbt.getInt( NBT_INSTANCE ) : -1; } - private static int getSessionID(@Nonnull ItemStack stack) { + private static int getSessionID( @Nonnull ItemStack stack ) + { CompoundTag nbt = stack.getTag(); - return nbt != null && nbt.contains(NBT_SESSION) ? nbt.getInt(NBT_SESSION) : -1; + return nbt != null && nbt.contains( NBT_SESSION ) ? nbt.getInt( NBT_SESSION ) : -1; } - private static void setInstanceID(@Nonnull ItemStack stack, int instanceID) { + private static void setInstanceID( @Nonnull ItemStack stack, int instanceID ) + { stack.getOrCreateTag() - .putInt(NBT_INSTANCE, instanceID); + .putInt( NBT_INSTANCE, instanceID ); } - private static void setSessionID(@Nonnull ItemStack stack, int sessionID) { + private static void setSessionID( @Nonnull ItemStack stack, int sessionID ) + { stack.getOrCreateTag() - .putInt(NBT_SESSION, sessionID); + .putInt( NBT_SESSION, sessionID ); } @Override - public IMount createDataMount(@Nonnull ItemStack stack, @Nonnull World world) { - int id = this.getComputerID(stack); - if (id >= 0) { - return ComputerCraftAPI.createSaveDirMount(world, "computer/" + id, ComputerCraft.computerSpaceLimit); + public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) + { + int id = this.getComputerID( stack ); + if( id >= 0 ) + { + return ComputerCraftAPI.createSaveDirMount( world, "computer/" + id, ComputerCraft.computerSpaceLimit ); } return null; } diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java b/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java index e2f4b1a43..ac2d7303d 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java @@ -6,26 +6,28 @@ package dan200.computercraft.shared.pocket.items; -import javax.annotation.Nonnull; - import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ComputerFamily; - import net.minecraft.item.ItemStack; -public final class PocketComputerItemFactory { +import javax.annotation.Nonnull; + +public final class PocketComputerItemFactory +{ private PocketComputerItemFactory() {} @Nonnull - public static ItemStack create(int id, String label, int colour, ComputerFamily family, IPocketUpgrade upgrade) { - switch (family) { - case NORMAL: - return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL.create(id, label, colour, upgrade); - case ADVANCED: - return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED.create(id, label, colour, upgrade); - default: - return ItemStack.EMPTY; + public static ItemStack create( int id, String label, int colour, ComputerFamily family, IPocketUpgrade upgrade ) + { + switch( family ) + { + case NORMAL: + return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL.create( id, label, colour, upgrade ); + case ADVANCED: + return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED.create( id, label, colour, upgrade ); + default: + return ItemStack.EMPTY; } } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java index 7c649807a..d4e9e1929 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java @@ -6,36 +6,40 @@ package dan200.computercraft.shared.pocket.peripherals; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.pocket.AbstractPocketUpgrade; import dan200.computercraft.api.pocket.IPocketAccess; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.modem.ModemState; - import net.minecraft.entity.Entity; import net.minecraft.util.Identifier; -public class PocketModem extends AbstractPocketUpgrade { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class PocketModem extends AbstractPocketUpgrade +{ private final boolean advanced; - public PocketModem(boolean advanced) { - super(new Identifier("computercraft", advanced ? "wireless_modem_advanced" : "wireless_modem_normal"), - advanced ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL); + public PocketModem( boolean advanced ) + { + super( new Identifier( "computercraft", advanced ? "wireless_modem_advanced" : "wireless_modem_normal" ), + advanced ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL ); this.advanced = advanced; } @Nullable @Override - public IPeripheral createPeripheral(@Nonnull IPocketAccess access) { - return new PocketModemPeripheral(this.advanced); + public IPeripheral createPeripheral( @Nonnull IPocketAccess access ) + { + return new PocketModemPeripheral( this.advanced ); } @Override - public void update(@Nonnull IPocketAccess access, @Nullable IPeripheral peripheral) { - if (!(peripheral instanceof PocketModemPeripheral)) { + public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) + { + if( !(peripheral instanceof PocketModemPeripheral) ) + { return; } @@ -43,13 +47,15 @@ public class PocketModem extends AbstractPocketUpgrade { PocketModemPeripheral modem = (PocketModemPeripheral) peripheral; - if (entity != null) { - modem.setLocation(entity.getEntityWorld(), entity.getCameraPosVec(1)); + if( entity != null ) + { + modem.setLocation( entity.getEntityWorld(), entity.getCameraPosVec( 1 ) ); } ModemState state = modem.getModemState(); - if (state.pollChanged()) { - access.setLight(state.isOpen() ? 0xBA0000 : -1); + if( state.pollChanged() ) + { + access.setLight( state.isOpen() ? 0xBA0000 : -1 ); } } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java index 75a8cf013..e4a9c1ff8 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java @@ -6,42 +6,47 @@ package dan200.computercraft.shared.pocket.peripherals; -import javax.annotation.Nonnull; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.peripheral.modem.ModemState; import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; - import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class PocketModemPeripheral extends WirelessModemPeripheral { +import javax.annotation.Nonnull; + +public class PocketModemPeripheral extends WirelessModemPeripheral +{ private World world = null; private Vec3d position = Vec3d.ZERO; - public PocketModemPeripheral(boolean advanced) { - super(new ModemState(), advanced); + public PocketModemPeripheral( boolean advanced ) + { + super( new ModemState(), advanced ); } - void setLocation(World world, Vec3d position) { + void setLocation( World world, Vec3d position ) + { this.position = position; this.world = world; } @Nonnull @Override - public World getWorld() { + public World getWorld() + { return this.world; } @Nonnull @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { return this.position; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return other instanceof PocketModemPeripheral; } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java index 31fadf87a..b5c98c7ad 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java @@ -6,42 +6,47 @@ package dan200.computercraft.shared.pocket.peripherals; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.pocket.AbstractPocketUpgrade; import dan200.computercraft.api.pocket.IPocketAccess; import dan200.computercraft.shared.ComputerCraftRegistry; - import net.minecraft.entity.Entity; import net.minecraft.util.Identifier; -public class PocketSpeaker extends AbstractPocketUpgrade { - public PocketSpeaker() { - super(new Identifier("computercraft", "speaker"), ComputerCraftRegistry.ModBlocks.SPEAKER); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class PocketSpeaker extends AbstractPocketUpgrade +{ + public PocketSpeaker() + { + super( new Identifier( "computercraft", "speaker" ), ComputerCraftRegistry.ModBlocks.SPEAKER ); } @Nullable @Override - public IPeripheral createPeripheral(@Nonnull IPocketAccess access) { + public IPeripheral createPeripheral( @Nonnull IPocketAccess access ) + { return new PocketSpeakerPeripheral(); } @Override - public void update(@Nonnull IPocketAccess access, @Nullable IPeripheral peripheral) { - if (!(peripheral instanceof PocketSpeakerPeripheral)) { + public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) + { + if( !(peripheral instanceof PocketSpeakerPeripheral) ) + { return; } PocketSpeakerPeripheral speaker = (PocketSpeakerPeripheral) peripheral; Entity entity = access.getEntity(); - if (entity != null) { - speaker.setLocation(entity.getEntityWorld(), entity.getCameraPosVec(1)); + if( entity != null ) + { + speaker.setLocation( entity.getEntityWorld(), entity.getCameraPosVec( 1 ) ); } speaker.update(); - access.setLight(speaker.madeSound(20) ? 0x3320fc : -1); + access.setLight( speaker.madeSound( 20 ) ? 0x3320fc : -1 ); } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java index 901c509ac..b1a451b78 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java @@ -8,31 +8,35 @@ package dan200.computercraft.shared.pocket.peripherals; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral; - import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class PocketSpeakerPeripheral extends SpeakerPeripheral { +public class PocketSpeakerPeripheral extends SpeakerPeripheral +{ private World world = null; private Vec3d position = Vec3d.ZERO; - void setLocation(World world, Vec3d position) { + void setLocation( World world, Vec3d position ) + { this.position = position; this.world = world; } @Override - public World getWorld() { + public World getWorld() + { return this.world; } @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { return this.world != null ? this.position : null; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return other instanceof PocketSpeakerPeripheral; } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java index c9693c509..79faf31e1 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java +++ b/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java @@ -6,14 +6,11 @@ package dan200.computercraft.shared.pocket.recipes; -import javax.annotation.Nonnull; - import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.shared.PocketUpgrades; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.RecipeSerializer; @@ -22,36 +19,46 @@ import net.minecraft.recipe.SpecialRecipeSerializer; import net.minecraft.util.Identifier; import net.minecraft.world.World; -public final class PocketComputerUpgradeRecipe extends SpecialCraftingRecipe { - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>(PocketComputerUpgradeRecipe::new); +import javax.annotation.Nonnull; - private PocketComputerUpgradeRecipe(Identifier identifier) { - super(identifier); +public final class PocketComputerUpgradeRecipe extends SpecialCraftingRecipe +{ + public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( PocketComputerUpgradeRecipe::new ); + + private PocketComputerUpgradeRecipe( Identifier identifier ) + { + super( identifier ); } @Nonnull @Override - public ItemStack getOutput() { - return PocketComputerItemFactory.create(-1, null, -1, ComputerFamily.NORMAL, null); + public ItemStack getOutput() + { + return PocketComputerItemFactory.create( -1, null, -1, ComputerFamily.NORMAL, null ); } @Override - public boolean matches(@Nonnull CraftingInventory inventory, @Nonnull World world) { - return !this.craft(inventory).isEmpty(); + public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) + { + return !this.craft( inventory ).isEmpty(); } @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inventory) { + public ItemStack craft( @Nonnull CraftingInventory inventory ) + { // Scan the grid for a pocket computer ItemStack computer = ItemStack.EMPTY; int computerX = -1; int computerY = -1; computer: - for (int y = 0; y < inventory.getHeight(); y++) { - for (int x = 0; x < inventory.getWidth(); x++) { - ItemStack item = inventory.getStack(x + y * inventory.getWidth()); - if (!item.isEmpty() && item.getItem() instanceof ItemPocketComputer) { + for( int y = 0; y < inventory.getHeight(); y++ ) + { + for( int x = 0; x < inventory.getWidth(); x++ ) + { + ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); + if( !item.isEmpty() && item.getItem() instanceof ItemPocketComputer ) + { computer = item; computerX = x; computerY = y; @@ -60,55 +67,67 @@ public final class PocketComputerUpgradeRecipe extends SpecialCraftingRecipe { } } - if (computer.isEmpty()) { + if( computer.isEmpty() ) + { return ItemStack.EMPTY; } ItemPocketComputer itemComputer = (ItemPocketComputer) computer.getItem(); - if (ItemPocketComputer.getUpgrade(computer) != null) { + if( ItemPocketComputer.getUpgrade( computer ) != null ) + { return ItemStack.EMPTY; } // Check for upgrades around the item IPocketUpgrade upgrade = null; - for (int y = 0; y < inventory.getHeight(); y++) { - for (int x = 0; x < inventory.getWidth(); x++) { - ItemStack item = inventory.getStack(x + y * inventory.getWidth()); - if (x == computerX && y == computerY) { + for( int y = 0; y < inventory.getHeight(); y++ ) + { + for( int x = 0; x < inventory.getWidth(); x++ ) + { + ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); + if( x == computerX && y == computerY ) + { continue; } - if (x == computerX && y == computerY - 1) { - upgrade = PocketUpgrades.get(item); - if (upgrade == null) { + if( x == computerX && y == computerY - 1 ) + { + upgrade = PocketUpgrades.get( item ); + if( upgrade == null ) + { return ItemStack.EMPTY; } - } else if (!item.isEmpty()) { + } + else if( !item.isEmpty() ) + { return ItemStack.EMPTY; } } } - if (upgrade == null) { + if( upgrade == null ) + { return ItemStack.EMPTY; } // Construct the new stack ComputerFamily family = itemComputer.getFamily(); - int computerID = itemComputer.getComputerID(computer); - String label = itemComputer.getLabel(computer); - int colour = itemComputer.getColour(computer); - return PocketComputerItemFactory.create(computerID, label, colour, family, upgrade); + int computerID = itemComputer.getComputerID( computer ); + String label = itemComputer.getLabel( computer ); + int colour = itemComputer.getColour( computer ); + return PocketComputerItemFactory.create( computerID, label, colour, family, upgrade ); } @Override - public boolean fits(int x, int y) { + public boolean fits( int x, int y ) + { return x >= 2 && y >= 2; } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } } diff --git a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java index 09654af93..cf16b9904 100644 --- a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java +++ b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java @@ -30,8 +30,10 @@ import dan200.computercraft.shared.turtle.FurnaceRefuelHandler; import dan200.computercraft.shared.turtle.SignInspectHandler; import dan200.computercraft.shared.util.Config; import dan200.computercraft.shared.util.TickScheduler; - +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerBlockEntityEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.CommandBlockBlockEntity; import net.minecraft.item.Item; @@ -41,14 +43,12 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; - -public final class ComputerCraftProxyCommon { +public final class ComputerCraftProxyCommon +{ private static MinecraftServer server; - public static void init() { + public static void init() + { NetworkHandler.setup(); registerProviders(); @@ -56,84 +56,91 @@ public final class ComputerCraftProxyCommon { ArgumentSerializers.register(); - ComputerCraftAPI.registerGenericSource(new InventoryMethods()); + ComputerCraftAPI.registerGenericSource( new InventoryMethods() ); } - private static void registerProviders() { - ComputerCraftAPI.registerPeripheralProvider((world, pos, side) -> { - BlockEntity tile = world.getBlockEntity(pos); - return tile instanceof IPeripheralTile ? ((IPeripheralTile) tile).getPeripheral(side) : null; - }); + private static void registerProviders() + { + ComputerCraftAPI.registerPeripheralProvider( ( world, pos, side ) -> { + BlockEntity tile = world.getBlockEntity( pos ); + return tile instanceof IPeripheralTile ? ((IPeripheralTile) tile).getPeripheral( side ) : null; + } ); - ComputerCraftAPI.registerPeripheralProvider((world, pos, side) -> { - BlockEntity tile = world.getBlockEntity(pos); + ComputerCraftAPI.registerPeripheralProvider( ( world, pos, side ) -> { + BlockEntity tile = world.getBlockEntity( pos ); return ComputerCraft.enableCommandBlock && tile instanceof CommandBlockBlockEntity ? - new CommandBlockPeripheral((CommandBlockBlockEntity) tile) : null; - }); + new CommandBlockPeripheral( (CommandBlockBlockEntity) tile ) : null; + } ); // Register bundled power providers - ComputerCraftAPI.registerBundledRedstoneProvider(new DefaultBundledRedstoneProvider()); + ComputerCraftAPI.registerBundledRedstoneProvider( new DefaultBundledRedstoneProvider() ); // Register media providers - ComputerCraftAPI.registerMediaProvider(stack -> { + ComputerCraftAPI.registerMediaProvider( stack -> { Item item = stack.getItem(); - if (item instanceof IMedia) { + if( item instanceof IMedia ) + { return (IMedia) item; } - if (item instanceof MusicDiscItem) { + if( item instanceof MusicDiscItem ) + { return RecordMedia.INSTANCE; } return null; - }); + } ); } - private static void registerHandlers() { - CommandRegistrationCallback.EVENT.register(CommandComputerCraft::register); + private static void registerHandlers() + { + CommandRegistrationCallback.EVENT.register( CommandComputerCraft::register ); - ServerTickEvents.START_SERVER_TICK.register(server -> { + ServerTickEvents.START_SERVER_TICK.register( server -> { MainThread.executePendingTasks(); ComputerCraft.serverComputerRegistry.update(); TickScheduler.tick(); - }); + } ); - ServerLifecycleEvents.SERVER_STARTED.register(server -> { + ServerLifecycleEvents.SERVER_STARTED.register( server -> { ComputerCraftProxyCommon.server = server; ComputerCraft.serverComputerRegistry.reset(); WirelessNetwork.resetNetworks(); MainThread.reset(); Tracking.reset(); - }); + } ); - ServerLifecycleEvents.SERVER_STOPPING.register(server -> { + ServerLifecycleEvents.SERVER_STOPPING.register( server -> { ComputerCraft.serverComputerRegistry.reset(); WirelessNetwork.resetNetworks(); MainThread.reset(); Tracking.reset(); ComputerCraftProxyCommon.server = null; - }); + } ); ServerBlockEntityEvents.BLOCK_ENTITY_UNLOAD.register( ( blockEntity, world ) -> { - if(blockEntity instanceof TileGeneric ) { - ((TileGeneric)blockEntity).onChunkUnloaded(); + if( blockEntity instanceof TileGeneric ) + { + ((TileGeneric) blockEntity).onChunkUnloaded(); } - }); + } ); // Config - ServerLifecycleEvents.SERVER_STARTING.register(Config::serverStarting); - ServerLifecycleEvents.SERVER_STOPPING.register(Config::serverStopping); + ServerLifecycleEvents.SERVER_STARTING.register( Config::serverStarting ); + ServerLifecycleEvents.SERVER_STOPPING.register( Config::serverStopping ); - TurtleEvent.EVENT_BUS.register(FurnaceRefuelHandler.INSTANCE); - TurtleEvent.EVENT_BUS.register(new TurtlePermissions()); - TurtleEvent.EVENT_BUS.register(new SignInspectHandler()); + TurtleEvent.EVENT_BUS.register( FurnaceRefuelHandler.INSTANCE ); + TurtleEvent.EVENT_BUS.register( new TurtlePermissions() ); + TurtleEvent.EVENT_BUS.register( new SignInspectHandler() ); } - public static void registerLoot() { - registerCondition("block_named", BlockNamedEntityLootCondition.TYPE); - registerCondition("player_creative", PlayerCreativeLootCondition.TYPE); - registerCondition("has_id", HasComputerIdLootCondition.TYPE); + public static void registerLoot() + { + registerCondition( "block_named", BlockNamedEntityLootCondition.TYPE ); + registerCondition( "player_creative", PlayerCreativeLootCondition.TYPE ); + registerCondition( "has_id", HasComputerIdLootCondition.TYPE ); } - private static void registerCondition(String name, LootConditionType serializer) { - Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, name), serializer); + private static void registerCondition( String name, LootConditionType serializer ) + { + Registry.register( Registry.LOOT_CONDITION_TYPE, new Identifier( ComputerCraft.MOD_ID, name ), serializer ); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java b/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java index 414613758..6ca4aaadd 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java +++ b/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java @@ -6,58 +6,65 @@ package dan200.computercraft.shared.turtle; -import javax.annotation.Nonnull; - import com.google.common.eventbus.Subscribe; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.block.entity.FurnaceBlockEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler { +import javax.annotation.Nonnull; + +public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler +{ public static final FurnaceRefuelHandler INSTANCE = new FurnaceRefuelHandler(); - private FurnaceRefuelHandler() { + private FurnaceRefuelHandler() + { } @Subscribe - public static void onTurtleRefuel(TurtleRefuelEvent event) { - if (event.getHandler() == null && getFuelPerItem(event.getStack()) > 0) { - event.setHandler(INSTANCE); + public static void onTurtleRefuel( TurtleRefuelEvent event ) + { + if( event.getHandler() == null && getFuelPerItem( event.getStack() ) > 0 ) + { + event.setHandler( INSTANCE ); } } @Override - public int refuel(@Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit) { - ItemStorage storage = ItemStorage.wrap(turtle.getInventory()); - ItemStack stack = storage.take(slot, limit, ItemStack.EMPTY, false); - int fuelToGive = getFuelPerItem(stack) * stack.getCount(); + public int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit ) + { + ItemStorage storage = ItemStorage.wrap( turtle.getInventory() ); + ItemStack stack = storage.take( slot, limit, ItemStack.EMPTY, false ); + int fuelToGive = getFuelPerItem( stack ) * stack.getCount(); // Store the replacement item in the inventory Item replacementStack = stack.getItem() - .getRecipeRemainder(); - if (replacementStack != null) { - ItemStack remainder = InventoryUtil.storeItems(new ItemStack(replacementStack), storage, turtle.getSelectedSlot()); - if (!remainder.isEmpty()) { - WorldUtil.dropItemStack(remainder, - turtle.getWorld(), - turtle.getPosition(), - turtle.getDirection() - .getOpposite()); + .getRecipeRemainder(); + if( replacementStack != null ) + { + ItemStack remainder = InventoryUtil.storeItems( new ItemStack( replacementStack ), storage, turtle.getSelectedSlot() ); + if( !remainder.isEmpty() ) + { + WorldUtil.dropItemStack( remainder, + turtle.getWorld(), + turtle.getPosition(), + turtle.getDirection() + .getOpposite() ); } } return fuelToGive; } - private static int getFuelPerItem(@Nonnull ItemStack stack) { + private static int getFuelPerItem( @Nonnull ItemStack stack ) + { int burnTime = FurnaceBlockEntity.createFuelTimeMap() - .getOrDefault(stack.getItem(), 0); + .getOrDefault( stack.getItem(), 0 ); return (burnTime * 5) / 100; } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java b/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java index 27bc2e98c..83308b347 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java +++ b/src/main/java/dan200/computercraft/shared/turtle/SignInspectHandler.java @@ -5,28 +5,30 @@ */ package dan200.computercraft.shared.turtle; -import java.util.HashMap; -import java.util.Map; - import com.google.common.eventbus.Subscribe; - import dan200.computercraft.api.turtle.event.TurtleBlockEvent; import dan200.computercraft.fabric.mixin.SignBlockEntityAccess; - import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.SignBlockEntity; -public class SignInspectHandler { +import java.util.HashMap; +import java.util.Map; + +public class SignInspectHandler +{ @Subscribe - public void onTurtleInspect(TurtleBlockEvent.Inspect event) { - BlockEntity be = event.getWorld().getBlockEntity(event.getPos()); - if (be instanceof SignBlockEntity) { - SignBlockEntity sbe = (SignBlockEntity)be; + public void onTurtleInspect( TurtleBlockEvent.Inspect event ) + { + BlockEntity be = event.getWorld().getBlockEntity( event.getPos() ); + if( be instanceof SignBlockEntity ) + { + SignBlockEntity sbe = (SignBlockEntity) be; Map textTable = new HashMap<>(); - for(int k = 0; k < 4; k++) { - textTable.put(k+1, ((SignBlockEntityAccess)sbe).getText()[k].asString()); + for( int k = 0; k < 4; k++ ) + { + textTable.put( k + 1, ((SignBlockEntityAccess) sbe).getText()[k].asString() ); } - event.getData().put("text", textTable); + event.getData().put( "text", textTable ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java index c10c2c1fd..f577bac63 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -6,16 +6,7 @@ package dan200.computercraft.shared.turtle.apis; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.lua.*; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleCommandResult; @@ -27,44 +18,33 @@ import dan200.computercraft.core.apis.IAPIEnvironment; import dan200.computercraft.core.asm.TaskCallback; import dan200.computercraft.core.tracking.TrackingField; import dan200.computercraft.shared.peripheral.generic.data.ItemData; -import dan200.computercraft.shared.turtle.core.InteractDirection; -import dan200.computercraft.shared.turtle.core.MoveDirection; -import dan200.computercraft.shared.turtle.core.TurnDirection; -import dan200.computercraft.shared.turtle.core.TurtleCompareCommand; -import dan200.computercraft.shared.turtle.core.TurtleCompareToCommand; -import dan200.computercraft.shared.turtle.core.TurtleDetectCommand; -import dan200.computercraft.shared.turtle.core.TurtleDropCommand; -import dan200.computercraft.shared.turtle.core.TurtleEquipCommand; -import dan200.computercraft.shared.turtle.core.TurtleInspectCommand; -import dan200.computercraft.shared.turtle.core.TurtleMoveCommand; -import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; -import dan200.computercraft.shared.turtle.core.TurtleRefuelCommand; -import dan200.computercraft.shared.turtle.core.TurtleSuckCommand; -import dan200.computercraft.shared.turtle.core.TurtleToolCommand; -import dan200.computercraft.shared.turtle.core.TurtleTransferToCommand; -import dan200.computercraft.shared.turtle.core.TurtleTurnCommand; - -import net.minecraft.item.Item; +import dan200.computercraft.shared.turtle.core.*; import net.minecraft.item.ItemStack; -import net.minecraft.util.registry.Registry; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; /** * The turtle API allows you to control your turtle. * * @cc.module turtle */ -public class TurtleAPI implements ILuaAPI { +public class TurtleAPI implements ILuaAPI +{ private final IAPIEnvironment environment; private final ITurtleAccess turtle; - public TurtleAPI(IAPIEnvironment environment, ITurtleAccess turtle) { + public TurtleAPI( IAPIEnvironment environment, ITurtleAccess turtle ) + { this.environment = environment; this.turtle = turtle; } @Override - public String[] getNames() { - return new String[] {"turtle"}; + public String[] getNames() + { + return new String[] { "turtle" }; } /** @@ -75,13 +55,15 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the turtle could not move. */ @LuaFunction - public final MethodResult forward() { - return this.trackCommand(new TurtleMoveCommand(MoveDirection.FORWARD)); + public final MethodResult forward() + { + return this.trackCommand( new TurtleMoveCommand( MoveDirection.FORWARD ) ); } - private MethodResult trackCommand(ITurtleCommand command) { - this.environment.addTrackingChange(TrackingField.TURTLE_OPS); - return this.turtle.executeCommand(command); + private MethodResult trackCommand( ITurtleCommand command ) + { + this.environment.addTrackingChange( TrackingField.TURTLE_OPS ); + return this.turtle.executeCommand( command ); } /** @@ -92,8 +74,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the turtle could not move. */ @LuaFunction - public final MethodResult back() { - return this.trackCommand(new TurtleMoveCommand(MoveDirection.BACK)); + public final MethodResult back() + { + return this.trackCommand( new TurtleMoveCommand( MoveDirection.BACK ) ); } /** @@ -104,8 +87,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the turtle could not move. */ @LuaFunction - public final MethodResult up() { - return this.trackCommand(new TurtleMoveCommand(MoveDirection.UP)); + public final MethodResult up() + { + return this.trackCommand( new TurtleMoveCommand( MoveDirection.UP ) ); } /** @@ -116,8 +100,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the turtle could not move. */ @LuaFunction - public final MethodResult down() { - return this.trackCommand(new TurtleMoveCommand(MoveDirection.DOWN)); + public final MethodResult down() + { + return this.trackCommand( new TurtleMoveCommand( MoveDirection.DOWN ) ); } /** @@ -128,8 +113,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the turtle could not turn. */ @LuaFunction - public final MethodResult turnLeft() { - return this.trackCommand(new TurtleTurnCommand(TurnDirection.LEFT)); + public final MethodResult turnLeft() + { + return this.trackCommand( new TurtleTurnCommand( TurnDirection.LEFT ) ); } /** @@ -140,8 +126,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the turtle could not turn. */ @LuaFunction - public final MethodResult turnRight() { - return this.trackCommand(new TurtleTurnCommand(TurnDirection.RIGHT)); + public final MethodResult turnRight() + { + return this.trackCommand( new TurtleTurnCommand( TurnDirection.RIGHT ) ); } /** @@ -156,9 +143,10 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason no block was broken. */ @LuaFunction - public final MethodResult dig(Optional side) { - this.environment.addTrackingChange(TrackingField.TURTLE_OPS); - return this.trackCommand(TurtleToolCommand.dig(InteractDirection.FORWARD, side.orElse(null))); + public final MethodResult dig( Optional side ) + { + this.environment.addTrackingChange( TrackingField.TURTLE_OPS ); + return this.trackCommand( TurtleToolCommand.dig( InteractDirection.FORWARD, side.orElse( null ) ) ); } /** @@ -170,9 +158,10 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason no block was broken. */ @LuaFunction - public final MethodResult digUp(Optional side) { - this.environment.addTrackingChange(TrackingField.TURTLE_OPS); - return this.trackCommand(TurtleToolCommand.dig(InteractDirection.UP, side.orElse(null))); + public final MethodResult digUp( Optional side ) + { + this.environment.addTrackingChange( TrackingField.TURTLE_OPS ); + return this.trackCommand( TurtleToolCommand.dig( InteractDirection.UP, side.orElse( null ) ) ); } /** @@ -184,9 +173,10 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason no block was broken. */ @LuaFunction - public final MethodResult digDown(Optional side) { - this.environment.addTrackingChange(TrackingField.TURTLE_OPS); - return this.trackCommand(TurtleToolCommand.dig(InteractDirection.DOWN, side.orElse(null))); + public final MethodResult digDown( Optional side ) + { + this.environment.addTrackingChange( TrackingField.TURTLE_OPS ); + return this.trackCommand( TurtleToolCommand.dig( InteractDirection.DOWN, side.orElse( null ) ) ); } /** @@ -203,8 +193,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the block was not placed. */ @LuaFunction - public final MethodResult place(IArguments args) { - return this.trackCommand(new TurtlePlaceCommand(InteractDirection.FORWARD, args.getAll())); + public final MethodResult place( IArguments args ) + { + return this.trackCommand( new TurtlePlaceCommand( InteractDirection.FORWARD, args.getAll() ) ); } /** @@ -218,8 +209,9 @@ public class TurtleAPI implements ILuaAPI { * @see #place For more information about placing items. */ @LuaFunction - public final MethodResult placeUp(IArguments args) { - return this.trackCommand(new TurtlePlaceCommand(InteractDirection.UP, args.getAll())); + public final MethodResult placeUp( IArguments args ) + { + return this.trackCommand( new TurtlePlaceCommand( InteractDirection.UP, args.getAll() ) ); } /** @@ -233,8 +225,9 @@ public class TurtleAPI implements ILuaAPI { * @see #place For more information about placing items. */ @LuaFunction - public final MethodResult placeDown(IArguments args) { - return this.trackCommand(new TurtlePlaceCommand(InteractDirection.DOWN, args.getAll())); + public final MethodResult placeDown( IArguments args ) + { + return this.trackCommand( new TurtlePlaceCommand( InteractDirection.DOWN, args.getAll() ) ); } /** @@ -248,14 +241,17 @@ public class TurtleAPI implements ILuaAPI { * @see #select */ @LuaFunction - public final MethodResult drop(Optional count) throws LuaException { - return this.trackCommand(new TurtleDropCommand(InteractDirection.FORWARD, checkCount(count))); + public final MethodResult drop( Optional count ) throws LuaException + { + return this.trackCommand( new TurtleDropCommand( InteractDirection.FORWARD, checkCount( count ) ) ); } - private static int checkCount(Optional countArg) throws LuaException { - int count = countArg.orElse(64); - if (count < 0 || count > 64) { - throw new LuaException("Item count " + count + " out of range"); + private static int checkCount( Optional countArg ) throws LuaException + { + int count = countArg.orElse( 64 ); + if( count < 0 || count > 64 ) + { + throw new LuaException( "Item count " + count + " out of range" ); } return count; } @@ -271,8 +267,9 @@ public class TurtleAPI implements ILuaAPI { * @see #select */ @LuaFunction - public final MethodResult dropUp(Optional count) throws LuaException { - return this.trackCommand(new TurtleDropCommand(InteractDirection.UP, checkCount(count))); + public final MethodResult dropUp( Optional count ) throws LuaException + { + return this.trackCommand( new TurtleDropCommand( InteractDirection.UP, checkCount( count ) ) ); } /** @@ -286,8 +283,9 @@ public class TurtleAPI implements ILuaAPI { * @see #select */ @LuaFunction - public final MethodResult dropDown(Optional count) throws LuaException { - return this.trackCommand(new TurtleDropCommand(InteractDirection.DOWN, checkCount(count))); + public final MethodResult dropDown( Optional count ) throws LuaException + { + return this.trackCommand( new TurtleDropCommand( InteractDirection.DOWN, checkCount( count ) ) ); } /** @@ -303,17 +301,20 @@ public class TurtleAPI implements ILuaAPI { */ @LuaFunction - public final MethodResult select(int slot) throws LuaException { - int actualSlot = checkSlot(slot); - return this.turtle.executeCommand(turtle -> { - turtle.setSelectedSlot(actualSlot); + public final MethodResult select( int slot ) throws LuaException + { + int actualSlot = checkSlot( slot ); + return this.turtle.executeCommand( turtle -> { + turtle.setSelectedSlot( actualSlot ); return TurtleCommandResult.success(); - }); + } ); } - private static int checkSlot(int slot) throws LuaException { - if (slot < 1 || slot > 16) { - throw new LuaException("Slot number " + slot + " out of range"); + private static int checkSlot( int slot ) throws LuaException + { + if( slot < 1 || slot > 16 ) + { + throw new LuaException( "Slot number " + slot + " out of range" ); } return slot - 1; } @@ -326,15 +327,17 @@ public class TurtleAPI implements ILuaAPI { * @throws LuaException If the slot is out of range. */ @LuaFunction - public final int getItemCount(Optional slot) throws LuaException { - int actualSlot = checkSlot(slot).orElse(this.turtle.getSelectedSlot()); + public final int getItemCount( Optional slot ) throws LuaException + { + int actualSlot = checkSlot( slot ).orElse( this.turtle.getSelectedSlot() ); return this.turtle.getInventory() - .getStack(actualSlot) - .getCount(); + .getStack( actualSlot ) + .getCount(); } - private static Optional checkSlot(Optional slot) throws LuaException { - return slot.isPresent() ? Optional.of(checkSlot(slot.get())) : Optional.empty(); + private static Optional checkSlot( Optional slot ) throws LuaException + { + return slot.isPresent() ? Optional.of( checkSlot( slot.get() ) ) : Optional.empty(); } /** @@ -347,11 +350,12 @@ public class TurtleAPI implements ILuaAPI { * @throws LuaException If the slot is out of range. */ @LuaFunction - public final int getItemSpace(Optional slot) throws LuaException { - int actualSlot = checkSlot(slot).orElse(this.turtle.getSelectedSlot()); + public final int getItemSpace( Optional slot ) throws LuaException + { + int actualSlot = checkSlot( slot ).orElse( this.turtle.getSelectedSlot() ); ItemStack stack = this.turtle.getInventory() - .getStack(actualSlot); - return stack.isEmpty() ? 64 : Math.min(stack.getMaxCount(), 64) - stack.getCount(); + .getStack( actualSlot ); + return stack.isEmpty() ? 64 : Math.min( stack.getMaxCount(), 64 ) - stack.getCount(); } /** @@ -361,8 +365,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If there is a solid block in front. */ @LuaFunction - public final MethodResult detect() { - return this.trackCommand(new TurtleDetectCommand(InteractDirection.FORWARD)); + public final MethodResult detect() + { + return this.trackCommand( new TurtleDetectCommand( InteractDirection.FORWARD ) ); } /** @@ -372,8 +377,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If there is a solid block in front. */ @LuaFunction - public final MethodResult detectUp() { - return this.trackCommand(new TurtleDetectCommand(InteractDirection.UP)); + public final MethodResult detectUp() + { + return this.trackCommand( new TurtleDetectCommand( InteractDirection.UP ) ); } /** @@ -383,8 +389,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If there is a solid block in front. */ @LuaFunction - public final MethodResult detectDown() { - return this.trackCommand(new TurtleDetectCommand(InteractDirection.DOWN)); + public final MethodResult detectDown() + { + return this.trackCommand( new TurtleDetectCommand( InteractDirection.DOWN ) ); } /** @@ -394,8 +401,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If the block and item are equal. */ @LuaFunction - public final MethodResult compare() { - return this.trackCommand(new TurtleCompareCommand(InteractDirection.FORWARD)); + public final MethodResult compare() + { + return this.trackCommand( new TurtleCompareCommand( InteractDirection.FORWARD ) ); } /** @@ -405,8 +413,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If the block and item are equal. */ @LuaFunction - public final MethodResult compareUp() { - return this.trackCommand(new TurtleCompareCommand(InteractDirection.UP)); + public final MethodResult compareUp() + { + return this.trackCommand( new TurtleCompareCommand( InteractDirection.UP ) ); } /** @@ -416,8 +425,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If the block and item are equal. */ @LuaFunction - public final MethodResult compareDown() { - return this.trackCommand(new TurtleCompareCommand(InteractDirection.DOWN)); + public final MethodResult compareDown() + { + return this.trackCommand( new TurtleCompareCommand( InteractDirection.DOWN ) ); } /** @@ -429,8 +439,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason nothing was attacked. */ @LuaFunction - public final MethodResult attack(Optional side) { - return this.trackCommand(TurtleToolCommand.attack(InteractDirection.FORWARD, side.orElse(null))); + public final MethodResult attack( Optional side ) + { + return this.trackCommand( TurtleToolCommand.attack( InteractDirection.FORWARD, side.orElse( null ) ) ); } /** @@ -442,8 +453,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason nothing was attacked. */ @LuaFunction - public final MethodResult attackUp(Optional side) { - return this.trackCommand(TurtleToolCommand.attack(InteractDirection.UP, side.orElse(null))); + public final MethodResult attackUp( Optional side ) + { + return this.trackCommand( TurtleToolCommand.attack( InteractDirection.UP, side.orElse( null ) ) ); } /** @@ -455,8 +467,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason nothing was attacked. */ @LuaFunction - public final MethodResult attackDown(Optional side) { - return this.trackCommand(TurtleToolCommand.attack(InteractDirection.DOWN, side.orElse(null))); + public final MethodResult attackDown( Optional side ) + { + return this.trackCommand( TurtleToolCommand.attack( InteractDirection.DOWN, side.orElse( null ) ) ); } /** @@ -471,8 +484,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the no items were picked up. */ @LuaFunction - public final MethodResult suck(Optional count) throws LuaException { - return this.trackCommand(new TurtleSuckCommand(InteractDirection.FORWARD, checkCount(count))); + public final MethodResult suck( Optional count ) throws LuaException + { + return this.trackCommand( new TurtleSuckCommand( InteractDirection.FORWARD, checkCount( count ) ) ); } /** @@ -485,8 +499,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the no items were picked up. */ @LuaFunction - public final MethodResult suckUp(Optional count) throws LuaException { - return this.trackCommand(new TurtleSuckCommand(InteractDirection.UP, checkCount(count))); + public final MethodResult suckUp( Optional count ) throws LuaException + { + return this.trackCommand( new TurtleSuckCommand( InteractDirection.UP, checkCount( count ) ) ); } /** @@ -499,8 +514,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn string|nil The reason the no items were picked up. */ @LuaFunction - public final MethodResult suckDown(Optional count) throws LuaException { - return this.trackCommand(new TurtleSuckCommand(InteractDirection.DOWN, checkCount(count))); + public final MethodResult suckDown( Optional count ) throws LuaException + { + return this.trackCommand( new TurtleSuckCommand( InteractDirection.DOWN, checkCount( count ) ) ); } /** @@ -513,7 +529,8 @@ public class TurtleAPI implements ILuaAPI { * @see #refuel(Optional) */ @LuaFunction - public final Object getFuelLevel() { + public final Object getFuelLevel() + { return this.turtle.isFuelNeeded() ? this.turtle.getFuelLevel() : "unlimited"; } @@ -554,12 +571,14 @@ public class TurtleAPI implements ILuaAPI { * @see #getFuelLimit() */ @LuaFunction - public final MethodResult refuel(Optional countA) throws LuaException { - int count = countA.orElse(Integer.MAX_VALUE); - if (count < 0) { - throw new LuaException("Refuel count " + count + " out of range"); + public final MethodResult refuel( Optional countA ) throws LuaException + { + int count = countA.orElse( Integer.MAX_VALUE ); + if( count < 0 ) + { + throw new LuaException( "Refuel count " + count + " out of range" ); } - return this.trackCommand(new TurtleRefuelCommand(count)); + return this.trackCommand( new TurtleRefuelCommand( count ) ); } /** @@ -571,8 +590,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If the two items are equal. */ @LuaFunction - public final MethodResult compareTo(int slot) throws LuaException { - return this.trackCommand(new TurtleCompareToCommand(checkSlot(slot))); + public final MethodResult compareTo( int slot ) throws LuaException + { + return this.trackCommand( new TurtleCompareToCommand( checkSlot( slot ) ) ); } /** @@ -586,10 +606,11 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn boolean If some items were successfully moved. */ @LuaFunction - public final MethodResult transferTo(int slotArg, Optional countArg) throws LuaException { - int slot = checkSlot(slotArg); - int count = checkCount(countArg); - return this.trackCommand(new TurtleTransferToCommand(slot, count)); + public final MethodResult transferTo( int slotArg, Optional countArg ) throws LuaException + { + int slot = checkSlot( slotArg ); + int count = checkCount( countArg ); + return this.trackCommand( new TurtleTransferToCommand( slot, count ) ); } /** @@ -599,7 +620,8 @@ public class TurtleAPI implements ILuaAPI { * @see #select */ @LuaFunction - public final int getSelectedSlot() { + public final int getSelectedSlot() + { return this.turtle.getSelectedSlot() + 1; } @@ -615,7 +637,8 @@ public class TurtleAPI implements ILuaAPI { * @see #refuel(Optional) */ @LuaFunction - public final Object getFuelLimit() { + public final Object getFuelLimit() + { return this.turtle.isFuelNeeded() ? this.turtle.getFuelLimit() : "unlimited"; } @@ -633,8 +656,9 @@ public class TurtleAPI implements ILuaAPI { * @see #equipRight() */ @LuaFunction - public final MethodResult equipLeft() { - return this.trackCommand(new TurtleEquipCommand(TurtleSide.LEFT)); + public final MethodResult equipLeft() + { + return this.trackCommand( new TurtleEquipCommand( TurtleSide.LEFT ) ); } /** @@ -651,8 +675,9 @@ public class TurtleAPI implements ILuaAPI { * @see #equipRight() */ @LuaFunction - public final MethodResult equipRight() { - return this.trackCommand(new TurtleEquipCommand(TurtleSide.RIGHT)); + public final MethodResult equipRight() + { + return this.trackCommand( new TurtleEquipCommand( TurtleSide.RIGHT ) ); } /** @@ -675,8 +700,9 @@ public class TurtleAPI implements ILuaAPI { * end}
    */ @LuaFunction - public final MethodResult inspect() { - return this.trackCommand(new TurtleInspectCommand(InteractDirection.FORWARD)); + public final MethodResult inspect() + { + return this.trackCommand( new TurtleInspectCommand( InteractDirection.FORWARD ) ); } /** @@ -687,8 +713,9 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn table|string Information about the above below, or a message explaining that there is no block. */ @LuaFunction - public final MethodResult inspectUp() { - return this.trackCommand(new TurtleInspectCommand(InteractDirection.UP)); + public final MethodResult inspectUp() + { + return this.trackCommand( new TurtleInspectCommand( InteractDirection.UP ) ); } /** @@ -699,57 +726,62 @@ public class TurtleAPI implements ILuaAPI { * @cc.treturn table|string Information about the block below, or a message explaining that there is no block. */ @LuaFunction - public final MethodResult inspectDown() { - return this.trackCommand(new TurtleInspectCommand(InteractDirection.DOWN)); + public final MethodResult inspectDown() + { + return this.trackCommand( new TurtleInspectCommand( InteractDirection.DOWN ) ); } /** * Get detailed information about the items in the given slot. * - * @param context The Lua context - * @param slot The slot to get information about. Defaults to the {@link #select selected slot}. + * @param context The Lua context + * @param slot The slot to get information about. Defaults to the {@link #select selected slot}. * @param detailed Whether to include "detailed" information. When {@code true} the method will contain much more information about the item at the - * cost of taking longer to run. + * cost of taking longer to run. * @return The command result. * @throws LuaException If the slot is out of range. - * @see InventoryMethods#getItemDetail Describes the information returned by a detailed query. * @cc.treturn nil|table Information about the given slot, or {@code nil} if it is empty. * @cc.usage Print the current slot, assuming it contains 13 dirt. * - *
    {@code
    +     * 
    {@code
          *     print(textutils.serialize(turtle.getItemDetail()))
          *     -- => {
          *     --  name = "minecraft:dirt",
          *     --  count = 13,
          *     -- }
          *     }
    + * @see InventoryMethods#getItemDetail Describes the information returned by a detailed query. */ @LuaFunction - public final MethodResult getItemDetail(ILuaContext context, Optional slot, Optional detailed) throws LuaException { - int actualSlot = checkSlot(slot).orElse(this.turtle.getSelectedSlot()); - return detailed.orElse(false) ? TaskCallback.make(context, () -> this.getItemDetail(actualSlot, true)) : MethodResult.of(this.getItemDetail(actualSlot, - false)); + public final MethodResult getItemDetail( ILuaContext context, Optional slot, Optional detailed ) throws LuaException + { + int actualSlot = checkSlot( slot ).orElse( this.turtle.getSelectedSlot() ); + return detailed.orElse( false ) ? TaskCallback.make( context, () -> this.getItemDetail( actualSlot, true ) ) : MethodResult.of( this.getItemDetail( actualSlot, + false ) ); } - private Object[] getItemDetail(int slot, boolean detailed) { + private Object[] getItemDetail( int slot, boolean detailed ) + { ItemStack stack = this.turtle.getInventory() - .getStack(slot); - if (stack.isEmpty()) { - return new Object[] {null}; + .getStack( slot ); + if( stack.isEmpty() ) + { + return new Object[] { null }; } Map table = detailed ? ItemData.fill( new HashMap<>(), stack ) : ItemData.fillBasicSafe( new HashMap<>(), stack ); - TurtleActionEvent event = new TurtleInspectItemEvent(this.turtle, stack, table, detailed); - if (TurtleEvent.post(event)) { + TurtleActionEvent event = new TurtleInspectItemEvent( this.turtle, stack, table, detailed ); + if( TurtleEvent.post( event ) ) + { return new Object[] { false, event.getFailureMessage() }; } - return new Object[] {table}; + return new Object[] { table }; } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java index 7abb6e687..cdecd21fd 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java @@ -6,14 +6,6 @@ package dan200.computercraft.shared.turtle.blocks; -import static dan200.computercraft.shared.util.WaterloggableHelpers.getWaterloggedFluidState; -import static dan200.computercraft.shared.util.WaterloggableHelpers.getWaterloggedStateForPlacement; -import static dan200.computercraft.shared.util.WaterloggableHelpers.updateWaterloggedPostPlacement; -import static net.minecraft.state.property.Properties.WATERLOGGED; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.computer.blocks.BlockComputerBase; import dan200.computercraft.shared.computer.blocks.TileComputerBase; @@ -21,12 +13,7 @@ import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.turtle.items.ITurtleItem; import dan200.computercraft.shared.turtle.items.TurtleItemFactory; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockRenderType; -import net.minecraft.block.BlockState; -import net.minecraft.block.ShapeContext; -import net.minecraft.block.Waterloggable; +import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.LivingEntity; @@ -47,72 +34,88 @@ import net.minecraft.world.BlockView; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; -public class BlockTurtle extends BlockComputerBase implements Waterloggable { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import static dan200.computercraft.shared.util.WaterloggableHelpers.*; +import static net.minecraft.state.property.Properties.WATERLOGGED; + +public class BlockTurtle extends BlockComputerBase implements Waterloggable +{ public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - private static final VoxelShape DEFAULT_SHAPE = VoxelShapes.cuboid(0.125, 0.125, 0.125, 0.875, 0.875, 0.875); + private static final VoxelShape DEFAULT_SHAPE = VoxelShapes.cuboid( 0.125, 0.125, 0.125, 0.875, 0.875, 0.875 ); - public BlockTurtle(Settings settings, ComputerFamily family, BlockEntityType type) { - super(settings, family, type); - this.setDefaultState(this.getStateManager().getDefaultState() - .with(FACING, Direction.NORTH) - .with(WATERLOGGED, false)); + public BlockTurtle( Settings settings, ComputerFamily family, BlockEntityType type ) + { + super( settings, family, type ); + this.setDefaultState( this.getStateManager().getDefaultState() + .with( FACING, Direction.NORTH ) + .with( WATERLOGGED, false ) ); } @Nonnull @Override @Deprecated - public BlockRenderType getRenderType(@Nonnull BlockState state) { + public BlockRenderType getRenderType( @Nonnull BlockState state ) + { return BlockRenderType.ENTITYBLOCK_ANIMATED; } @Nonnull @Override @Deprecated - public BlockState getStateForNeighborUpdate(@Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, - @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos) { - updateWaterloggedPostPlacement(state, world, pos); + public BlockState getStateForNeighborUpdate( @Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, + @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos ) + { + updateWaterloggedPostPlacement( state, world, pos ); return state; } @Nonnull @Override @Deprecated - public FluidState getFluidState(@Nonnull BlockState state) { - return getWaterloggedFluidState(state); + public FluidState getFluidState( @Nonnull BlockState state ) + { + return getWaterloggedFluidState( state ); } @Nonnull @Override @Deprecated - public VoxelShape getOutlineShape(@Nonnull BlockState state, BlockView world, @Nonnull BlockPos pos, @Nonnull ShapeContext context) { - BlockEntity tile = world.getBlockEntity(pos); - Vec3d offset = tile instanceof TileTurtle ? ((TileTurtle) tile).getRenderOffset(1.0f) : Vec3d.ZERO; - return offset.equals(Vec3d.ZERO) ? DEFAULT_SHAPE : DEFAULT_SHAPE.offset(offset.x, offset.y, offset.z); + public VoxelShape getOutlineShape( @Nonnull BlockState state, BlockView world, @Nonnull BlockPos pos, @Nonnull ShapeContext context ) + { + BlockEntity tile = world.getBlockEntity( pos ); + Vec3d offset = tile instanceof TileTurtle ? ((TileTurtle) tile).getRenderOffset( 1.0f ) : Vec3d.ZERO; + return offset.equals( Vec3d.ZERO ) ? DEFAULT_SHAPE : DEFAULT_SHAPE.offset( offset.x, offset.y, offset.z ); } @Override - public float getBlastResistance() { + public float getBlastResistance() + { // TODO Implement below functionality return 2000; } @Nullable @Override - public BlockState getPlacementState(ItemPlacementContext placement) { - return this.getDefaultState().with(FACING, placement.getPlayerFacing()) - .with(WATERLOGGED, getWaterloggedStateForPlacement(placement)); + public BlockState getPlacementState( ItemPlacementContext placement ) + { + return this.getDefaultState().with( FACING, placement.getPlayerFacing() ) + .with( WATERLOGGED, getWaterloggedStateForPlacement( placement ) ); } @Override - protected void appendProperties(StateManager.Builder builder) { - builder.add(FACING, WATERLOGGED); + protected void appendProperties( StateManager.Builder builder ) + { + builder.add( FACING, WATERLOGGED ); } @Nonnull @Override - protected ItemStack getItem(TileComputerBase tile) { - return tile instanceof TileTurtle ? TurtleItemFactory.create((TileTurtle) tile) : ItemStack.EMPTY; + protected ItemStack getItem( TileComputerBase tile ) + { + return tile instanceof TileTurtle ? TurtleItemFactory.create( (TileTurtle) tile ) : ItemStack.EMPTY; } // @Override @@ -128,40 +131,47 @@ public class BlockTurtle extends BlockComputerBase implements Waterl // } @Override - public void onPlaced(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable LivingEntity player, @Nonnull ItemStack stack) { - super.onPlaced(world, pos, state, player, stack); + public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable LivingEntity player, @Nonnull ItemStack stack ) + { + super.onPlaced( world, pos, state, player, stack ); - BlockEntity tile = world.getBlockEntity(pos); - if (!world.isClient && tile instanceof TileTurtle) { + BlockEntity tile = world.getBlockEntity( pos ); + if( !world.isClient && tile instanceof TileTurtle ) + { TileTurtle turtle = (TileTurtle) tile; - if (player instanceof PlayerEntity) { - ((TileTurtle) tile).setOwningPlayer(((PlayerEntity) player).getGameProfile()); + if( player instanceof PlayerEntity ) + { + ((TileTurtle) tile).setOwningPlayer( ((PlayerEntity) player).getGameProfile() ); } - if (stack.getItem() instanceof ITurtleItem) { + if( stack.getItem() instanceof ITurtleItem ) + { ITurtleItem item = (ITurtleItem) stack.getItem(); // Set Upgrades - for (TurtleSide side : TurtleSide.values()) { + for( TurtleSide side : TurtleSide.values() ) + { turtle.getAccess() - .setUpgrade(side, item.getUpgrade(stack, side)); + .setUpgrade( side, item.getUpgrade( stack, side ) ); } turtle.getAccess() - .setFuelLevel(item.getFuelLevel(stack)); + .setFuelLevel( item.getFuelLevel( stack ) ); // Set colour - int colour = item.getColour(stack); - if (colour != -1) { + int colour = item.getColour( stack ); + if( colour != -1 ) + { turtle.getAccess() - .setColour(colour); + .setColour( colour ); } // Set overlay - Identifier overlay = item.getOverlay(stack); - if (overlay != null) { - ((TurtleBrain) turtle.getAccess()).setOverlay(overlay); + Identifier overlay = item.getOverlay( stack ); + if( overlay != null ) + { + ((TurtleBrain) turtle.getAccess()).setOverlay( overlay ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java index 894afcd8e..38224df84 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java @@ -10,22 +10,22 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.computer.blocks.IComputerTile; - import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3d; -public interface ITurtleTile extends IComputerTile { +public interface ITurtleTile extends IComputerTile +{ int getColour(); Identifier getOverlay(); - ITurtleUpgrade getUpgrade(TurtleSide side); + ITurtleUpgrade getUpgrade( TurtleSide side ); ITurtleAccess getAccess(); - Vec3d getRenderOffset(float f); + Vec3d getRenderOffset( float f ); - float getRenderYaw(float f); + float getRenderYaw( float f ); - float getToolRenderAngle(TurtleSide side, float f); + float getToolRenderAngle( TurtleSide side, float f ); } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index 118de826c..091d757f9 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.turtle.blocks; -import java.util.Collections; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.mojang.authlib.GameProfile; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.ITurtleAccess; @@ -26,13 +21,7 @@ import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.turtle.apis.TurtleAPI; import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; -import dan200.computercraft.shared.util.DefaultInventory; -import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.NBTUtil; -import dan200.computercraft.shared.util.RedstoneUtil; -import dan200.computercraft.shared.util.WorldUtil; - +import dan200.computercraft.shared.util.*; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; @@ -53,63 +42,85 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; + +public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory +{ public static final int INVENTORY_SIZE = 16; public static final int INVENTORY_WIDTH = 4; public static final int INVENTORY_HEIGHT = 4; - private final DefaultedList m_inventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY); - private final DefaultedList m_previousInventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY); + private final DefaultedList m_inventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); + private final DefaultedList m_previousInventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); private boolean m_inventoryChanged = false; - private TurtleBrain m_brain = new TurtleBrain(this); + private TurtleBrain m_brain = new TurtleBrain( this ); private MoveState m_moveState = MoveState.NOT_MOVED; - public TileTurtle(BlockEntityType type, ComputerFamily family) { - super(type, family); + + public TileTurtle( BlockEntityType type, ComputerFamily family ) + { + super( type, family ); } @Override - protected void unload() { - if (!this.hasMoved()) { + protected void unload() + { + if( !this.hasMoved() ) + { super.unload(); } } @Override - public void destroy() { - if (!this.hasMoved()) { + public void destroy() + { + if( !this.hasMoved() ) + { // Stop computer super.destroy(); // Drop contents - if (!this.getWorld().isClient) { + if( !this.getWorld().isClient ) + { int size = this.size(); - for (int i = 0; i < size; i++) { - ItemStack stack = this.getStack(i); - if (!stack.isEmpty()) { - WorldUtil.dropItemStack(stack, this.getWorld(), this.getPos()); + for( int i = 0; i < size; i++ ) + { + ItemStack stack = this.getStack( i ); + if( !stack.isEmpty() ) + { + WorldUtil.dropItemStack( stack, this.getWorld(), this.getPos() ); } } } - } else { + } + else + { // Just turn off any redstone we had on - for (Direction dir : DirectionUtil.FACINGS) { - RedstoneUtil.propagateRedstoneOutput(this.getWorld(), this.getPos(), dir); + for( Direction dir : DirectionUtil.FACINGS ) + { + RedstoneUtil.propagateRedstoneOutput( this.getWorld(), this.getPos(), dir ); } } } - private boolean hasMoved() { + private boolean hasMoved() + { return this.m_moveState == MoveState.MOVED; } @Override - public int size() { + public int size() + { return INVENTORY_SIZE; } @Override - public boolean isEmpty() { - for (ItemStack stack : this.m_inventory) { - if (!stack.isEmpty()) { + public boolean isEmpty() + { + for( ItemStack stack : this.m_inventory ) + { + if( !stack.isEmpty() ) + { return false; } } @@ -118,88 +129,110 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Nonnull @Override - public ItemStack getStack(int slot) { - return slot >= 0 && slot < INVENTORY_SIZE ? this.m_inventory.get(slot) : ItemStack.EMPTY; + public ItemStack getStack( int slot ) + { + return slot >= 0 && slot < INVENTORY_SIZE ? this.m_inventory.get( slot ) : ItemStack.EMPTY; } @Nonnull @Override - public ItemStack removeStack(int slot, int count) { - if (count == 0) { + public ItemStack removeStack( int slot, int count ) + { + if( count == 0 ) + { return ItemStack.EMPTY; } - ItemStack stack = this.getStack(slot); - if (stack.isEmpty()) { + ItemStack stack = this.getStack( slot ); + if( stack.isEmpty() ) + { return ItemStack.EMPTY; } - if (stack.getCount() <= count) { - this.setStack(slot, ItemStack.EMPTY); + if( stack.getCount() <= count ) + { + this.setStack( slot, ItemStack.EMPTY ); return stack; } - ItemStack part = stack.split(count); + ItemStack part = stack.split( count ); this.onInventoryDefinitelyChanged(); return part; } @Nonnull @Override - public ItemStack removeStack(int slot) { - ItemStack result = this.getStack(slot); - this.setStack(slot, ItemStack.EMPTY); + public ItemStack removeStack( int slot ) + { + ItemStack result = this.getStack( slot ); + this.setStack( slot, ItemStack.EMPTY ); return result; } @Override - public void setStack(int i, @Nonnull ItemStack stack) { - if (i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual(stack, this.m_inventory.get(i))) { - this.m_inventory.set(i, stack); + public void setStack( int i, @Nonnull ItemStack stack ) + { + if( i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual( stack, this.m_inventory.get( i ) ) ) + { + this.m_inventory.set( i, stack ); this.onInventoryDefinitelyChanged(); } } @Override - public boolean canPlayerUse(@Nonnull PlayerEntity player) { - return this.isUsable(player, false); + public boolean canPlayerUse( @Nonnull PlayerEntity player ) + { + return this.isUsable( player, false ); } - private void onInventoryDefinitelyChanged() { + private void onInventoryDefinitelyChanged() + { super.markDirty(); this.m_inventoryChanged = true; } @Override - protected boolean canNameWithTag(PlayerEntity player) { + protected boolean canNameWithTag( PlayerEntity player ) + { return true; } @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { // Apply dye - ItemStack currentItem = player.getStackInHand(hand); - if (!currentItem.isEmpty()) { - if (currentItem.getItem() instanceof DyeItem) { + ItemStack currentItem = player.getStackInHand( hand ); + if( !currentItem.isEmpty() ) + { + if( currentItem.getItem() instanceof DyeItem ) + { // Dye to change turtle colour - if (!this.getWorld().isClient) { + if( !this.getWorld().isClient ) + { DyeColor dye = ((DyeItem) currentItem.getItem()).getColor(); - if (this.m_brain.getDyeColour() != dye) { - this.m_brain.setDyeColour(dye); - if (!player.isCreative()) { - currentItem.decrement(1); + if( this.m_brain.getDyeColour() != dye ) + { + this.m_brain.setDyeColour( dye ); + if( !player.isCreative() ) + { + currentItem.decrement( 1 ); } } } return ActionResult.SUCCESS; - } else if (currentItem.getItem() == Items.WATER_BUCKET && this.m_brain.getColour() != -1) { + } + else if( currentItem.getItem() == Items.WATER_BUCKET && this.m_brain.getColour() != -1 ) + { // Water to remove turtle colour - if (!this.getWorld().isClient) { - if (this.m_brain.getColour() != -1) { - this.m_brain.setColour(-1); - if (!player.isCreative()) { - player.setStackInHand(hand, new ItemStack(Items.BUCKET)); + if( !this.getWorld().isClient ) + { + if( this.m_brain.getColour() != -1 ) + { + this.m_brain.setColour( -1 ); + if( !player.isCreative() ) + { + player.setStackInHand( hand, new ItemStack( Items.BUCKET ) ); player.inventory.markDirty(); } } @@ -209,233 +242,276 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default } // Open GUI or whatever - return super.onActivate(player, hand, hit); + return super.onActivate( player, hand, hit ); } @Override - public void onNeighbourChange(@Nonnull BlockPos neighbour) { - if (this.m_moveState == MoveState.NOT_MOVED) { - super.onNeighbourChange(neighbour); + public void onNeighbourChange( @Nonnull BlockPos neighbour ) + { + if( this.m_moveState == MoveState.NOT_MOVED ) + { + super.onNeighbourChange( neighbour ); } } @Override - public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) { - if (this.m_moveState == MoveState.NOT_MOVED) { - super.onNeighbourTileEntityChange(neighbour); + public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) + { + if( this.m_moveState == MoveState.NOT_MOVED ) + { + super.onNeighbourTileEntityChange( neighbour ); } } @Override - public void tick() { + public void tick() + { super.tick(); this.m_brain.update(); - if (!this.getWorld().isClient && this.m_inventoryChanged) { + if( !this.getWorld().isClient && this.m_inventoryChanged ) + { ServerComputer computer = this.getServerComputer(); - if (computer != null) { - computer.queueEvent("turtle_inventory"); + if( computer != null ) + { + computer.queueEvent( "turtle_inventory" ); } this.m_inventoryChanged = false; - for (int n = 0; n < this.size(); n++) { - this.m_previousInventory.set(n, - this.getStack(n).copy()); + for( int n = 0; n < this.size(); n++ ) + { + this.m_previousInventory.set( n, + this.getStack( n ).copy() ); } } } @Override - protected void updateBlockState(ComputerState newState) { + protected void updateBlockState( ComputerState newState ) + { } @Nonnull @Override - public CompoundTag toTag(@Nonnull CompoundTag nbt) { + public CompoundTag toTag( @Nonnull CompoundTag nbt ) + { // Write inventory ListTag nbttaglist = new ListTag(); - for (int i = 0; i < INVENTORY_SIZE; i++) { - if (!this.m_inventory.get(i) - .isEmpty()) { + for( int i = 0; i < INVENTORY_SIZE; i++ ) + { + if( !this.m_inventory.get( i ) + .isEmpty() ) + { CompoundTag tag = new CompoundTag(); - tag.putByte("Slot", (byte) i); - this.m_inventory.get(i) - .toTag(tag); - nbttaglist.add(tag); + tag.putByte( "Slot", (byte) i ); + this.m_inventory.get( i ) + .toTag( tag ); + nbttaglist.add( tag ); } } - nbt.put("Items", nbttaglist); + nbt.put( "Items", nbttaglist ); // Write brain - nbt = this.m_brain.writeToNBT(nbt); + nbt = this.m_brain.writeToNBT( nbt ); - return super.toTag(nbt); + return super.toTag( nbt ); } // IDirectionalTile @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); // Read inventory - ListTag nbttaglist = nbt.getList("Items", NBTUtil.TAG_COMPOUND); + ListTag nbttaglist = nbt.getList( "Items", NBTUtil.TAG_COMPOUND ); this.m_inventory.clear(); this.m_previousInventory.clear(); - for (int i = 0; i < nbttaglist.size(); i++) { - CompoundTag tag = nbttaglist.getCompound(i); - int slot = tag.getByte("Slot") & 0xff; - if (slot < this.size()) { - this.m_inventory.set(slot, ItemStack.fromTag(tag)); - this.m_previousInventory.set(slot, this.m_inventory.get(slot) - .copy()); + for( int i = 0; i < nbttaglist.size(); i++ ) + { + CompoundTag tag = nbttaglist.getCompound( i ); + int slot = tag.getByte( "Slot" ) & 0xff; + if( slot < this.size() ) + { + this.m_inventory.set( slot, ItemStack.fromTag( tag ) ); + this.m_previousInventory.set( slot, this.m_inventory.get( slot ) + .copy() ); } } // Read state - this.m_brain.readFromNBT(nbt); + this.m_brain.readFromNBT( nbt ); } @Override - protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) { - return this.hasPeripheralUpgradeOnSide(localSide); + protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) + { + return this.hasPeripheralUpgradeOnSide( localSide ); } // ITurtleTile @Override - public Direction getDirection() { - return this.getCachedState().get(BlockTurtle.FACING); + public Direction getDirection() + { + return this.getCachedState().get( BlockTurtle.FACING ); } @Override - protected ServerComputer createComputer(int instanceID, int id) { - ServerComputer computer = new ServerComputer(this.getWorld(), - id, this.label, - instanceID, this.getFamily(), - ComputerCraft.turtleTermWidth, - ComputerCraft.turtleTermHeight); - computer.setPosition(this.getPos()); - computer.addAPI(new TurtleAPI(computer.getAPIEnvironment(), this.getAccess())); - this.m_brain.setupComputer(computer); + protected ServerComputer createComputer( int instanceID, int id ) + { + ServerComputer computer = new ServerComputer( this.getWorld(), + id, this.label, + instanceID, this.getFamily(), + ComputerCraft.turtleTermWidth, + ComputerCraft.turtleTermHeight ); + computer.setPosition( this.getPos() ); + computer.addAPI( new TurtleAPI( computer.getAPIEnvironment(), this.getAccess() ) ); + this.m_brain.setupComputer( computer ); return computer; } @Override - protected void writeDescription(@Nonnull CompoundTag nbt) { - super.writeDescription(nbt); - this.m_brain.writeDescription(nbt); + protected void writeDescription( @Nonnull CompoundTag nbt ) + { + super.writeDescription( nbt ); + this.m_brain.writeDescription( nbt ); } @Override - protected void readDescription(@Nonnull CompoundTag nbt) { - super.readDescription(nbt); - this.m_brain.readDescription(nbt); + protected void readDescription( @Nonnull CompoundTag nbt ) + { + super.readDescription( nbt ); + this.m_brain.readDescription( nbt ); } @Override - public ComputerProxy createProxy() { + public ComputerProxy createProxy() + { return this.m_brain.getProxy(); } - public void setDirection(Direction dir) { - if (dir.getAxis() == Direction.Axis.Y) { + public void setDirection( Direction dir ) + { + if( dir.getAxis() == Direction.Axis.Y ) + { dir = Direction.NORTH; } - this.world.setBlockState(this.pos, - this.getCachedState().with(BlockTurtle.FACING, dir)); + this.world.setBlockState( this.pos, + this.getCachedState().with( BlockTurtle.FACING, dir ) ); this.updateOutput(); this.updateInput(); this.onTileEntityChange(); } - public void onTileEntityChange() { + public void onTileEntityChange() + { super.markDirty(); } - private boolean hasPeripheralUpgradeOnSide(ComputerSide side) { + private boolean hasPeripheralUpgradeOnSide( ComputerSide side ) + { ITurtleUpgrade upgrade; - switch (side) { - case RIGHT: - upgrade = this.getUpgrade(TurtleSide.RIGHT); - break; - case LEFT: - upgrade = this.getUpgrade(TurtleSide.LEFT); - break; - default: - return false; + switch( side ) + { + case RIGHT: + upgrade = this.getUpgrade( TurtleSide.RIGHT ); + break; + case LEFT: + upgrade = this.getUpgrade( TurtleSide.LEFT ); + break; + default: + return false; } return upgrade != null && upgrade.getType() - .isPeripheral(); + .isPeripheral(); } // IInventory @Override - protected double getInteractRange(PlayerEntity player) { + protected double getInteractRange( PlayerEntity player ) + { return 12.0; } - public void notifyMoveStart() { - if (this.m_moveState == MoveState.NOT_MOVED) { + public void notifyMoveStart() + { + if( this.m_moveState == MoveState.NOT_MOVED ) + { this.m_moveState = MoveState.IN_PROGRESS; } } - public void notifyMoveEnd() { + public void notifyMoveEnd() + { // MoveState.MOVED is final - if (this.m_moveState == MoveState.IN_PROGRESS) { + if( this.m_moveState == MoveState.IN_PROGRESS ) + { this.m_moveState = MoveState.NOT_MOVED; } } @Override - public int getColour() { + public int getColour() + { return this.m_brain.getColour(); } @Override - public Identifier getOverlay() { + public Identifier getOverlay() + { return this.m_brain.getOverlay(); } @Override - public ITurtleUpgrade getUpgrade(TurtleSide side) { - return this.m_brain.getUpgrade(side); + public ITurtleUpgrade getUpgrade( TurtleSide side ) + { + return this.m_brain.getUpgrade( side ); } @Override - public ITurtleAccess getAccess() { + public ITurtleAccess getAccess() + { return this.m_brain; } @Override - public Vec3d getRenderOffset(float f) { - return this.m_brain.getRenderOffset(f); + public Vec3d getRenderOffset( float f ) + { + return this.m_brain.getRenderOffset( f ); } @Override - public float getRenderYaw(float f) { - return this.m_brain.getVisualYaw(f); + public float getRenderYaw( float f ) + { + return this.m_brain.getVisualYaw( f ); } @Override - public float getToolRenderAngle(TurtleSide side, float f) { - return this.m_brain.getToolRenderAngle(side, f); + public float getToolRenderAngle( TurtleSide side, float f ) + { + return this.m_brain.getToolRenderAngle( side, f ); } - void setOwningPlayer(GameProfile player) { - this.m_brain.setOwningPlayer(player); + void setOwningPlayer( GameProfile player ) + { + this.m_brain.setOwningPlayer( player ); this.markDirty(); } // Networking stuff @Override - public void markDirty() { + public void markDirty() + { super.markDirty(); - if (!this.m_inventoryChanged) { - for (int n = 0; n < this.size(); n++) { - if (!ItemStack.areEqual(this.getStack(n), this.m_previousInventory.get(n))) { + if( !this.m_inventoryChanged ) + { + for( int n = 0; n < this.size(); n++ ) + { + if( !ItemStack.areEqual( this.getStack( n ), this.m_previousInventory.get( n ) ) ) + { this.m_inventoryChanged = true; break; } @@ -444,30 +520,35 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default } @Override - public void clear() { + public void clear() + { boolean changed = false; - for (int i = 0; i < INVENTORY_SIZE; i++) { - if (!this.m_inventory.get(i) - .isEmpty()) { - this.m_inventory.set(i, ItemStack.EMPTY); + for( int i = 0; i < INVENTORY_SIZE; i++ ) + { + if( !this.m_inventory.get( i ) + .isEmpty() ) + { + this.m_inventory.set( i, ItemStack.EMPTY ); changed = true; } } - if (changed) { + if( changed ) + { this.onInventoryDefinitelyChanged(); } } // Privates - public void transferStateFrom(TileTurtle copy) { - super.transferStateFrom(copy); - Collections.copy(this.m_inventory, copy.m_inventory); - Collections.copy(this.m_previousInventory, copy.m_previousInventory); + public void transferStateFrom( TileTurtle copy ) + { + super.transferStateFrom( copy ); + Collections.copy( this.m_inventory, copy.m_inventory ); + Collections.copy( this.m_previousInventory, copy.m_previousInventory ); this.m_inventoryChanged = copy.m_inventoryChanged; this.m_brain = copy.m_brain; - this.m_brain.setOwner(this); + this.m_brain.setOwner( this ); // Mark the other turtle as having moved, and so its peripheral is dead. copy.m_moveState = MoveState.MOVED; @@ -475,11 +556,13 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Nullable @Override - public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) { - return new ContainerTurtle(id, inventory, this.m_brain); + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) + { + return new ContainerTurtle( id, inventory, this.m_brain ); } - enum MoveState { + enum MoveState + { NOT_MOVED, IN_PROGRESS, MOVED } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/InteractDirection.java b/src/main/java/dan200/computercraft/shared/turtle/core/InteractDirection.java index 00b58b318..2f22305e1 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/InteractDirection.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/InteractDirection.java @@ -7,21 +7,23 @@ package dan200.computercraft.shared.turtle.core; import dan200.computercraft.api.turtle.ITurtleAccess; - import net.minecraft.util.math.Direction; -public enum InteractDirection { +public enum InteractDirection +{ FORWARD, UP, DOWN; - public Direction toWorldDir(ITurtleAccess turtle) { - switch (this) { - case FORWARD: - default: - return turtle.getDirection(); - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; + public Direction toWorldDir( ITurtleAccess turtle ) + { + switch( this ) + { + case FORWARD: + default: + return turtle.getDirection(); + case UP: + return Direction.UP; + case DOWN: + return Direction.DOWN; } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/MoveDirection.java b/src/main/java/dan200/computercraft/shared/turtle/core/MoveDirection.java index 60df15898..0364db549 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/MoveDirection.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/MoveDirection.java @@ -7,24 +7,26 @@ package dan200.computercraft.shared.turtle.core; import dan200.computercraft.api.turtle.ITurtleAccess; - import net.minecraft.util.math.Direction; -public enum MoveDirection { +public enum MoveDirection +{ FORWARD, BACK, UP, DOWN; - public Direction toWorldDir(ITurtleAccess turtle) { - switch (this) { - case FORWARD: - default: - return turtle.getDirection(); - case BACK: - return turtle.getDirection() - .getOpposite(); - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; + public Direction toWorldDir( ITurtleAccess turtle ) + { + switch( this ) + { + case FORWARD: + default: + return turtle.getDirection(); + case BACK: + return turtle.getDirection() + .getOpposite(); + case UP: + return Direction.UP; + case DOWN: + return Direction.DOWN; } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurnDirection.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurnDirection.java index bcf7015c6..becb48380 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurnDirection.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurnDirection.java @@ -6,6 +6,7 @@ package dan200.computercraft.shared.turtle.core; -public enum TurnDirection { +public enum TurnDirection +{ LEFT, RIGHT, } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index 3cbecea92..870fcb2a0 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -6,45 +6,20 @@ package dan200.computercraft.shared.turtle.core; -import static dan200.computercraft.shared.common.IColouredItem.NBT_COLOUR; -import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED; - -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.base.Objects; import com.mojang.authlib.GameProfile; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.ILuaCallback; import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.api.turtle.*; import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.shared.TurtleUpgrades; import dan200.computercraft.shared.computer.blocks.ComputerProxy; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.Holiday; -import dan200.computercraft.shared.util.HolidayUtil; -import dan200.computercraft.shared.util.InventoryDelegate; -import dan200.computercraft.shared.util.NBTUtil; - +import dan200.computercraft.shared.util.*; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -64,7 +39,16 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class TurtleBrain implements ITurtleAccess { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; +import java.util.concurrent.TimeUnit; + +import static dan200.computercraft.shared.common.IColouredItem.NBT_COLOUR; +import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED; + +public class TurtleBrain implements ITurtleAccess +{ public static final String NBT_RIGHT_UPGRADE = "RightUpgrade"; public static final String NBT_RIGHT_UPGRADE_DATA = "RightUpgradeNbt"; public static final String NBT_LEFT_UPGRADE = "LeftUpgrade"; @@ -76,9 +60,9 @@ public class TurtleBrain implements ITurtleAccess { private static final int ANIM_DURATION = 8; private final Queue m_commandQueue = new ArrayDeque<>(); - private final Map m_upgrades = new EnumMap<>(TurtleSide.class); - private final Map peripherals = new EnumMap<>(TurtleSide.class); - private final Map m_upgradeNBTData = new EnumMap<>(TurtleSide.class); + private final Map m_upgrades = new EnumMap<>( TurtleSide.class ); + private final Map peripherals = new EnumMap<>( TurtleSide.class ); + private final Map m_upgradeNBTData = new EnumMap<>( TurtleSide.class ); TurtlePlayer m_cachedPlayer; private TileTurtle m_owner; private final Inventory m_inventory = (InventoryDelegate) () -> this.m_owner; @@ -93,74 +77,92 @@ public class TurtleBrain implements ITurtleAccess { private int m_animationProgress = 0; private int m_lastAnimationProgress = 0; - public TurtleBrain(TileTurtle turtle) { + public TurtleBrain( TileTurtle turtle ) + { this.m_owner = turtle; } - public TileTurtle getOwner() { + public TileTurtle getOwner() + { return this.m_owner; } - public void setOwner(TileTurtle owner) { + public void setOwner( TileTurtle owner ) + { this.m_owner = owner; } - public ComputerProxy getProxy() { - if (this.m_proxy == null) { - this.m_proxy = new ComputerProxy(() -> this.m_owner); + public ComputerProxy getProxy() + { + if( this.m_proxy == null ) + { + this.m_proxy = new ComputerProxy( () -> this.m_owner ); } return this.m_proxy; } - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return this.m_owner.getFamily(); } - public void setupComputer(ServerComputer computer) { - this.updatePeripherals(computer); + public void setupComputer( ServerComputer computer ) + { + this.updatePeripherals( computer ); } - private void updatePeripherals(ServerComputer serverComputer) { - if (serverComputer == null) { + private void updatePeripherals( ServerComputer serverComputer ) + { + if( serverComputer == null ) + { return; } // Update peripherals - for (TurtleSide side : TurtleSide.values()) { - ITurtleUpgrade upgrade = this.getUpgrade(side); + for( TurtleSide side : TurtleSide.values() ) + { + ITurtleUpgrade upgrade = this.getUpgrade( side ); IPeripheral peripheral = null; - if (upgrade != null && upgrade.getType() - .isPeripheral()) { - peripheral = upgrade.createPeripheral(this, side); + if( upgrade != null && upgrade.getType() + .isPeripheral() ) + { + peripheral = upgrade.createPeripheral( this, side ); } - IPeripheral existing = this.peripherals.get(side); - if (existing == peripheral || (existing != null && peripheral != null && existing.equals(peripheral))) { + IPeripheral existing = this.peripherals.get( side ); + if( existing == peripheral || (existing != null && peripheral != null && existing.equals( peripheral )) ) + { // If the peripheral is the same, just use that. peripheral = existing; - } else { + } + else + { // Otherwise update our map - this.peripherals.put(side, peripheral); + this.peripherals.put( side, peripheral ); } // Always update the computer: it may not be the same computer as before! - serverComputer.setPeripheral(toDirection(side), peripheral); + serverComputer.setPeripheral( toDirection( side ), peripheral ); } } - private static ComputerSide toDirection(TurtleSide side) { - switch (side) { - case LEFT: - return ComputerSide.LEFT; - case RIGHT: - default: - return ComputerSide.RIGHT; + private static ComputerSide toDirection( TurtleSide side ) + { + switch( side ) + { + case LEFT: + return ComputerSide.LEFT; + case RIGHT: + default: + return ComputerSide.RIGHT; } } - public void update() { + public void update() + { World world = this.getWorld(); - if (!world.isClient) { + if( !world.isClient ) + { // Advance movement this.updateCommands(); @@ -173,30 +175,36 @@ public class TurtleBrain implements ITurtleAccess { this.updateAnimation(); // Advance upgrades - if (!this.m_upgrades.isEmpty()) { - for (Map.Entry entry : this.m_upgrades.entrySet()) { + if( !this.m_upgrades.isEmpty() ) + { + for( Map.Entry entry : this.m_upgrades.entrySet() ) + { entry.getValue() - .update(this, entry.getKey()); + .update( this, entry.getKey() ); } } } @Nonnull @Override - public World getWorld() { + public World getWorld() + { return this.m_owner.getWorld(); } @Nonnull @Override - public BlockPos getPosition() { + public BlockPos getPosition() + { return this.m_owner.getPos(); } @Override - public boolean teleportTo(@Nonnull World world, @Nonnull BlockPos pos) { - if (world.isClient || this.getWorld().isClient) { - throw new UnsupportedOperationException("Cannot teleport on the client"); + public boolean teleportTo( @Nonnull World world, @Nonnull BlockPos pos ) + { + if( world.isClient || this.getWorld().isClient ) + { + throw new UnsupportedOperationException( "Cannot teleport on the client" ); } // Cache info about the old turtle (so we don't access this after we delete ourselves) @@ -205,51 +213,58 @@ public class TurtleBrain implements ITurtleAccess { BlockPos oldPos = this.m_owner.getPos(); BlockState oldBlock = this.m_owner.getCachedState(); - if (oldWorld == world && oldPos.equals(pos)) { + if( oldWorld == world && oldPos.equals( pos ) ) + { // Teleporting to the current position is a no-op return true; } // Ensure the chunk is loaded - if (!world.isChunkLoaded(pos)) { + if( !world.isChunkLoaded( pos ) ) + { return false; } // Ensure we're inside the world border - if (!world.getWorldBorder() - .contains(pos)) { + if( !world.getWorldBorder() + .contains( pos ) ) + { return false; } - FluidState existingFluid = world.getBlockState(pos) - .getFluidState(); + FluidState existingFluid = world.getBlockState( pos ) + .getFluidState(); BlockState newState = oldBlock - // We only mark this as waterlogged when travelling into a source block. This prevents us from spreading - // fluid by creating a new source when moving into a block, causing the next block to be almost full and - // then moving into that. - .with(WATERLOGGED, existingFluid.isIn(FluidTags.WATER) && existingFluid.isStill()); + // We only mark this as waterlogged when travelling into a source block. This prevents us from spreading + // fluid by creating a new source when moving into a block, causing the next block to be almost full and + // then moving into that. + .with( WATERLOGGED, existingFluid.isIn( FluidTags.WATER ) && existingFluid.isStill() ); oldOwner.notifyMoveStart(); - try { + try + { // Create a new turtle - if (world.setBlockState(pos, newState, 0)) { - Block block = world.getBlockState(pos) - .getBlock(); - if (block == oldBlock.getBlock()) { - BlockEntity newTile = world.getBlockEntity(pos); - if (newTile instanceof TileTurtle) { + if( world.setBlockState( pos, newState, 0 ) ) + { + Block block = world.getBlockState( pos ) + .getBlock(); + if( block == oldBlock.getBlock() ) + { + BlockEntity newTile = world.getBlockEntity( pos ); + if( newTile instanceof TileTurtle ) + { // Copy the old turtle state into the new turtle TileTurtle newTurtle = (TileTurtle) newTile; - newTurtle.setLocation(world, pos); - newTurtle.transferStateFrom(oldOwner); + newTurtle.setLocation( world, pos ); + newTurtle.transferStateFrom( oldOwner ); newTurtle.createServerComputer() - .setWorld(world); + .setWorld( world ); newTurtle.createServerComputer() - .setPosition(pos); + .setPosition( pos ); // Remove the old turtle - oldWorld.removeBlock(oldPos, false); + oldWorld.removeBlock( oldPos, false ); // Make sure everybody knows about it newTurtle.updateBlock(); @@ -260,9 +275,11 @@ public class TurtleBrain implements ITurtleAccess { } // Something went wrong, remove the newly created turtle - world.removeBlock(pos, false); + world.removeBlock( pos, false ); } - } finally { + } + finally + { // whatever happens, unblock old turtle in case it's still in world oldOwner.notifyMoveEnd(); } @@ -272,75 +289,94 @@ public class TurtleBrain implements ITurtleAccess { @Nonnull @Override - public Vec3d getVisualPosition(float f) { - Vec3d offset = this.getRenderOffset(f); + public Vec3d getVisualPosition( float f ) + { + Vec3d offset = this.getRenderOffset( f ); BlockPos pos = this.m_owner.getPos(); - return new Vec3d(pos.getX() + 0.5 + offset.x, pos.getY() + 0.5 + offset.y, pos.getZ() + 0.5 + offset.z); + return new Vec3d( pos.getX() + 0.5 + offset.x, pos.getY() + 0.5 + offset.y, pos.getZ() + 0.5 + offset.z ); } @Override - public float getVisualYaw(float f) { + public float getVisualYaw( float f ) + { float yaw = this.getDirection().asRotation(); - switch (this.m_animation) { - case TURN_LEFT: { - yaw += 90.0f * (1.0f - this.getAnimationFraction(f)); - if (yaw >= 360.0f) { - yaw -= 360.0f; + switch( this.m_animation ) + { + case TURN_LEFT: + { + yaw += 90.0f * (1.0f - this.getAnimationFraction( f )); + if( yaw >= 360.0f ) + { + yaw -= 360.0f; + } + break; } - break; - } - case TURN_RIGHT: { - yaw += -90.0f * (1.0f - this.getAnimationFraction(f)); - if (yaw < 0.0f) { - yaw += 360.0f; + case TURN_RIGHT: + { + yaw += -90.0f * (1.0f - this.getAnimationFraction( f )); + if( yaw < 0.0f ) + { + yaw += 360.0f; + } + break; } - break; - } } return yaw; } @Nonnull @Override - public Direction getDirection() { + public Direction getDirection() + { return this.m_owner.getDirection(); } @Override - public void setDirection(@Nonnull Direction dir) { - this.m_owner.setDirection(dir); + public void setDirection( @Nonnull Direction dir ) + { + this.m_owner.setDirection( dir ); } @Override - public int getSelectedSlot() { + public int getSelectedSlot() + { return this.m_selectedSlot; } @Override - public void setSelectedSlot(int slot) { - if (this.getWorld().isClient) { - throw new UnsupportedOperationException("Cannot set the slot on the client"); + public void setSelectedSlot( int slot ) + { + if( this.getWorld().isClient ) + { + throw new UnsupportedOperationException( "Cannot set the slot on the client" ); } - if (slot >= 0 && slot < this.m_owner.size()) { + if( slot >= 0 && slot < this.m_owner.size() ) + { this.m_selectedSlot = slot; this.m_owner.onTileEntityChange(); } } @Override - public int getColour() { + public int getColour() + { return this.m_colourHex; } @Override - public void setColour(int colour) { - if (colour >= 0 && colour <= 0xFFFFFF) { - if (this.m_colourHex != colour) { + public void setColour( int colour ) + { + if( colour >= 0 && colour <= 0xFFFFFF ) + { + if( this.m_colourHex != colour ) + { this.m_colourHex = colour; this.m_owner.updateBlock(); } - } else if (this.m_colourHex != -1) { + } + else if( this.m_colourHex != -1 ) + { this.m_colourHex = -1; this.m_owner.updateBlock(); } @@ -348,91 +384,113 @@ public class TurtleBrain implements ITurtleAccess { @Nullable @Override - public GameProfile getOwningPlayer() { + public GameProfile getOwningPlayer() + { return this.m_owningPlayer; } @Override - public boolean isFuelNeeded() { + public boolean isFuelNeeded() + { return ComputerCraft.turtlesNeedFuel; } @Override - public int getFuelLevel() { - return Math.min(this.m_fuelLevel, this.getFuelLimit()); + public int getFuelLevel() + { + return Math.min( this.m_fuelLevel, this.getFuelLimit() ); } @Override - public void setFuelLevel(int level) { - this.m_fuelLevel = Math.min(level, this.getFuelLimit()); + public void setFuelLevel( int level ) + { + this.m_fuelLevel = Math.min( level, this.getFuelLimit() ); this.m_owner.onTileEntityChange(); } @Override - public int getFuelLimit() { - if (this.m_owner.getFamily() == ComputerFamily.ADVANCED) { + public int getFuelLimit() + { + if( this.m_owner.getFamily() == ComputerFamily.ADVANCED ) + { return ComputerCraft.advancedTurtleFuelLimit; - } else { + } + else + { return ComputerCraft.turtleFuelLimit; } } @Override - public boolean consumeFuel(int fuel) { - if (this.getWorld().isClient) { - throw new UnsupportedOperationException("Cannot consume fuel on the client"); + public boolean consumeFuel( int fuel ) + { + if( this.getWorld().isClient ) + { + throw new UnsupportedOperationException( "Cannot consume fuel on the client" ); } - if (!this.isFuelNeeded()) { + if( !this.isFuelNeeded() ) + { return true; } - int consumption = Math.max(fuel, 0); - if (this.getFuelLevel() >= consumption) { - this.setFuelLevel(this.getFuelLevel() - consumption); + int consumption = Math.max( fuel, 0 ); + if( this.getFuelLevel() >= consumption ) + { + this.setFuelLevel( this.getFuelLevel() - consumption ); return true; } return false; } @Override - public void addFuel(int fuel) { - if (this.getWorld().isClient) { - throw new UnsupportedOperationException("Cannot add fuel on the client"); + public void addFuel( int fuel ) + { + if( this.getWorld().isClient ) + { + throw new UnsupportedOperationException( "Cannot add fuel on the client" ); } - int addition = Math.max(fuel, 0); - this.setFuelLevel(this.getFuelLevel() + addition); + int addition = Math.max( fuel, 0 ); + this.setFuelLevel( this.getFuelLevel() + addition ); } @Nonnull @Override - public MethodResult executeCommand(@Nonnull ITurtleCommand command) { - if (this.getWorld().isClient) { - throw new UnsupportedOperationException("Cannot run commands on the client"); + public MethodResult executeCommand( @Nonnull ITurtleCommand command ) + { + if( this.getWorld().isClient ) + { + throw new UnsupportedOperationException( "Cannot run commands on the client" ); } // Issue command - int commandID = this.issueCommand(command); - return new CommandCallback(commandID).pull; + int commandID = this.issueCommand( command ); + return new CommandCallback( commandID ).pull; } - private int issueCommand(ITurtleCommand command) { - this.m_commandQueue.offer(new TurtleCommandQueueEntry(++this.m_commandsIssued, command)); + private int issueCommand( ITurtleCommand command ) + { + this.m_commandQueue.offer( new TurtleCommandQueueEntry( ++this.m_commandsIssued, command ) ); return this.m_commandsIssued; } @Override - public void playAnimation(@Nonnull TurtleAnimation animation) { - if (this.getWorld().isClient) { - throw new UnsupportedOperationException("Cannot play animations on the client"); + public void playAnimation( @Nonnull TurtleAnimation animation ) + { + if( this.getWorld().isClient ) + { + throw new UnsupportedOperationException( "Cannot play animations on the client" ); } this.m_animation = animation; - if (this.m_animation == TurtleAnimation.SHORT_WAIT) { + if( this.m_animation == TurtleAnimation.SHORT_WAIT ) + { this.m_animationProgress = ANIM_DURATION / 2; this.m_lastAnimationProgress = ANIM_DURATION / 2; - } else { + } + else + { this.m_animationProgress = 0; this.m_lastAnimationProgress = 0; } @@ -440,150 +498,182 @@ public class TurtleBrain implements ITurtleAccess { } @Override - public ITurtleUpgrade getUpgrade(@Nonnull TurtleSide side) { - return this.m_upgrades.get(side); + public ITurtleUpgrade getUpgrade( @Nonnull TurtleSide side ) + { + return this.m_upgrades.get( side ); } @Override - public void setUpgrade(@Nonnull TurtleSide side, ITurtleUpgrade upgrade) { + public void setUpgrade( @Nonnull TurtleSide side, ITurtleUpgrade upgrade ) + { // Remove old upgrade - if (this.m_upgrades.containsKey(side)) { - if (this.m_upgrades.get(side) == upgrade) { + if( this.m_upgrades.containsKey( side ) ) + { + if( this.m_upgrades.get( side ) == upgrade ) + { return; } - this.m_upgrades.remove(side); - } else { - if (upgrade == null) { + this.m_upgrades.remove( side ); + } + else + { + if( upgrade == null ) + { return; } } - this.m_upgradeNBTData.remove(side); + this.m_upgradeNBTData.remove( side ); // Set new upgrade - if (upgrade != null) { - this.m_upgrades.put(side, upgrade); + if( upgrade != null ) + { + this.m_upgrades.put( side, upgrade ); } // Notify clients and create peripherals - if (this.m_owner.getWorld() != null) { - this.updatePeripherals(this.m_owner.createServerComputer()); + if( this.m_owner.getWorld() != null ) + { + this.updatePeripherals( this.m_owner.createServerComputer() ); this.m_owner.updateBlock(); } } @Override - public IPeripheral getPeripheral(@Nonnull TurtleSide side) { - return this.peripherals.get(side); + public IPeripheral getPeripheral( @Nonnull TurtleSide side ) + { + return this.peripherals.get( side ); } @Nonnull @Override - public CompoundTag getUpgradeNBTData(TurtleSide side) { - CompoundTag nbt = this.m_upgradeNBTData.get(side); - if (nbt == null) { - this.m_upgradeNBTData.put(side, nbt = new CompoundTag()); + public CompoundTag getUpgradeNBTData( TurtleSide side ) + { + CompoundTag nbt = this.m_upgradeNBTData.get( side ); + if( nbt == null ) + { + this.m_upgradeNBTData.put( side, nbt = new CompoundTag() ); } return nbt; } @Override - public void updateUpgradeNBTData(@Nonnull TurtleSide side) { + public void updateUpgradeNBTData( @Nonnull TurtleSide side ) + { this.m_owner.updateBlock(); } @Nonnull @Override - public Inventory getInventory() { + public Inventory getInventory() + { return this.m_inventory; } - public void setOwningPlayer(GameProfile profile) { + public void setOwningPlayer( GameProfile profile ) + { this.m_owningPlayer = profile; } - private void updateCommands() { - if (this.m_animation != TurtleAnimation.NONE || this.m_commandQueue.isEmpty()) { + private void updateCommands() + { + if( this.m_animation != TurtleAnimation.NONE || this.m_commandQueue.isEmpty() ) + { return; } // If we've got a computer, ensure that we're allowed to perform work. ServerComputer computer = this.m_owner.getServerComputer(); - if (computer != null && !computer.getComputer() - .getMainThreadMonitor() - .canWork()) { + if( computer != null && !computer.getComputer() + .getMainThreadMonitor() + .canWork() ) + { return; } // Pull a new command TurtleCommandQueueEntry nextCommand = this.m_commandQueue.poll(); - if (nextCommand == null) { + if( nextCommand == null ) + { return; } // Execute the command long start = System.nanoTime(); - TurtleCommandResult result = nextCommand.command.execute(this); + TurtleCommandResult result = nextCommand.command.execute( this ); long end = System.nanoTime(); // Dispatch the callback - if (computer == null) { + if( computer == null ) + { return; } computer.getComputer() - .getMainThreadMonitor() - .trackWork(end - start, TimeUnit.NANOSECONDS); + .getMainThreadMonitor() + .trackWork( end - start, TimeUnit.NANOSECONDS ); int callbackID = nextCommand.callbackID; - if (callbackID < 0) { + if( callbackID < 0 ) + { return; } - if (result != null && result.isSuccess()) { + if( result != null && result.isSuccess() ) + { Object[] results = result.getResults(); - if (results != null) { + if( results != null ) + { Object[] arguments = new Object[results.length + 2]; arguments[0] = callbackID; arguments[1] = true; - System.arraycopy(results, 0, arguments, 2, results.length); - computer.queueEvent("turtle_response", arguments); - } else { - computer.queueEvent("turtle_response", new Object[] { + System.arraycopy( results, 0, arguments, 2, results.length ); + computer.queueEvent( "turtle_response", arguments ); + } + else + { + computer.queueEvent( "turtle_response", new Object[] { callbackID, true, - }); + } ); } - } else { - computer.queueEvent("turtle_response", new Object[] { + } + else + { + computer.queueEvent( "turtle_response", new Object[] { callbackID, false, result != null ? result.getErrorMessage() : null, - }); + } ); } } - private void updateAnimation() { - if (this.m_animation != TurtleAnimation.NONE) { + private void updateAnimation() + { + if( this.m_animation != TurtleAnimation.NONE ) + { World world = this.getWorld(); - if (ComputerCraft.turtlesCanPush) { + if( ComputerCraft.turtlesCanPush ) + { // Advance entity pushing - if (this.m_animation == TurtleAnimation.MOVE_FORWARD || this.m_animation == TurtleAnimation.MOVE_BACK || this.m_animation == TurtleAnimation.MOVE_UP || this.m_animation == TurtleAnimation.MOVE_DOWN) { + if( this.m_animation == TurtleAnimation.MOVE_FORWARD || this.m_animation == TurtleAnimation.MOVE_BACK || this.m_animation == TurtleAnimation.MOVE_UP || this.m_animation == TurtleAnimation.MOVE_DOWN ) + { BlockPos pos = this.getPosition(); Direction moveDir; - switch (this.m_animation) { - case MOVE_FORWARD: - default: - moveDir = this.getDirection(); - break; - case MOVE_BACK: - moveDir = this.getDirection().getOpposite(); - break; - case MOVE_UP: - moveDir = Direction.UP; - break; - case MOVE_DOWN: - moveDir = Direction.DOWN; - break; + switch( this.m_animation ) + { + case MOVE_FORWARD: + default: + moveDir = this.getDirection(); + break; + case MOVE_BACK: + moveDir = this.getDirection().getOpposite(); + break; + case MOVE_UP: + moveDir = Direction.UP; + break; + case MOVE_DOWN: + moveDir = Direction.DOWN; + break; } double minX = pos.getX(); @@ -594,63 +684,78 @@ public class TurtleBrain implements ITurtleAccess { double maxZ = minZ + 1.0; float pushFrac = 1.0f - (float) (this.m_animationProgress + 1) / ANIM_DURATION; - float push = Math.max(pushFrac + 0.0125f, 0.0f); - if (moveDir.getOffsetX() < 0) { + float push = Math.max( pushFrac + 0.0125f, 0.0f ); + if( moveDir.getOffsetX() < 0 ) + { minX += moveDir.getOffsetX() * push; - } else { + } + else + { maxX -= moveDir.getOffsetX() * push; } - if (moveDir.getOffsetY() < 0) { + if( moveDir.getOffsetY() < 0 ) + { minY += moveDir.getOffsetY() * push; - } else { + } + else + { maxY -= moveDir.getOffsetY() * push; } - if (moveDir.getOffsetZ() < 0) { + if( moveDir.getOffsetZ() < 0 ) + { minZ += moveDir.getOffsetZ() * push; - } else { + } + else + { maxZ -= moveDir.getOffsetZ() * push; } - Box aabb = new Box(minX, minY, minZ, maxX, maxY, maxZ); - List list = world.getEntitiesByClass(Entity.class, aabb, EntityPredicates.EXCEPT_SPECTATOR); - if (!list.isEmpty()) { + Box aabb = new Box( minX, minY, minZ, maxX, maxY, maxZ ); + List list = world.getEntitiesByClass( Entity.class, aabb, EntityPredicates.EXCEPT_SPECTATOR ); + if( !list.isEmpty() ) + { double pushStep = 1.0f / ANIM_DURATION; double pushStepX = moveDir.getOffsetX() * pushStep; double pushStepY = moveDir.getOffsetY() * pushStep; double pushStepZ = moveDir.getOffsetZ() * pushStep; - for (Entity entity : list) { - entity.move(MovementType.PISTON, new Vec3d(pushStepX, pushStepY, pushStepZ)); + for( Entity entity : list ) + { + entity.move( MovementType.PISTON, new Vec3d( pushStepX, pushStepY, pushStepZ ) ); } } } } // Advance valentines day easter egg - if (world.isClient && this.m_animation == TurtleAnimation.MOVE_FORWARD && this.m_animationProgress == 4) { + if( world.isClient && this.m_animation == TurtleAnimation.MOVE_FORWARD && this.m_animationProgress == 4 ) + { // Spawn love pfx if valentines day Holiday currentHoliday = HolidayUtil.getCurrentHoliday(); - if (currentHoliday == Holiday.VALENTINES) { - Vec3d position = this.getVisualPosition(1.0f); - if (position != null) { + if( currentHoliday == Holiday.VALENTINES ) + { + Vec3d position = this.getVisualPosition( 1.0f ); + if( position != null ) + { double x = position.x + world.random.nextGaussian() * 0.1; double y = position.y + 0.5 + world.random.nextGaussian() * 0.1; double z = position.z + world.random.nextGaussian() * 0.1; - world.addParticle(ParticleTypes.HEART, - x, - y, - z, - world.random.nextGaussian() * 0.02, - world.random.nextGaussian() * 0.02, - world.random.nextGaussian() * 0.02); + world.addParticle( ParticleTypes.HEART, + x, + y, + z, + world.random.nextGaussian() * 0.02, + world.random.nextGaussian() * 0.02, + world.random.nextGaussian() * 0.02 ); } } } // Wait for anim completion this.m_lastAnimationProgress = this.m_animationProgress; - if (++this.m_animationProgress >= ANIM_DURATION) { + if( ++this.m_animationProgress >= ANIM_DURATION ) + { this.m_animation = TurtleAnimation.NONE; this.m_animationProgress = 0; this.m_lastAnimationProgress = 0; @@ -658,56 +763,66 @@ public class TurtleBrain implements ITurtleAccess { } } - public Vec3d getRenderOffset(float f) { - switch (this.m_animation) { - case MOVE_FORWARD: - case MOVE_BACK: - case MOVE_UP: - case MOVE_DOWN: { - // Get direction - Direction dir; - switch (this.m_animation) { + public Vec3d getRenderOffset( float f ) + { + switch( this.m_animation ) + { case MOVE_FORWARD: - default: - dir = this.getDirection(); - break; case MOVE_BACK: - dir = this.getDirection().getOpposite(); - break; case MOVE_UP: - dir = Direction.UP; - break; case MOVE_DOWN: - dir = Direction.DOWN; - break; - } + { + // Get direction + Direction dir; + switch( this.m_animation ) + { + case MOVE_FORWARD: + default: + dir = this.getDirection(); + break; + case MOVE_BACK: + dir = this.getDirection().getOpposite(); + break; + case MOVE_UP: + dir = Direction.UP; + break; + case MOVE_DOWN: + dir = Direction.DOWN; + break; + } - double distance = -1.0 + this.getAnimationFraction(f); - return new Vec3d(distance * dir.getOffsetX(), distance * dir.getOffsetY(), distance * dir.getOffsetZ()); - } - default: { - return Vec3d.ZERO; - } + double distance = -1.0 + this.getAnimationFraction( f ); + return new Vec3d( distance * dir.getOffsetX(), distance * dir.getOffsetY(), distance * dir.getOffsetZ() ); + } + default: + { + return Vec3d.ZERO; + } } } - private float getAnimationFraction(float f) { + private float getAnimationFraction( float f ) + { float next = (float) this.m_animationProgress / ANIM_DURATION; float previous = (float) this.m_lastAnimationProgress / ANIM_DURATION; return previous + (next - previous) * f; } - public void readFromNBT(CompoundTag nbt) { - this.readCommon(nbt); + public void readFromNBT( CompoundTag nbt ) + { + this.readCommon( nbt ); // Read state - this.m_selectedSlot = nbt.getInt(NBT_SLOT); + this.m_selectedSlot = nbt.getInt( NBT_SLOT ); // Read owner - if (nbt.contains("Owner", NBTUtil.TAG_COMPOUND)) { - CompoundTag owner = nbt.getCompound("Owner"); - this.m_owningPlayer = new GameProfile(new UUID(owner.getLong("UpperId"), owner.getLong("LowerId")), owner.getString("Name")); - } else { + if( nbt.contains( "Owner", NBTUtil.TAG_COMPOUND ) ) + { + CompoundTag owner = nbt.getCompound( "Owner" ); + this.m_owningPlayer = new GameProfile( new UUID( owner.getLong( "UpperId" ), owner.getLong( "LowerId" ) ), owner.getString( "Name" ) ); + } + else + { this.m_owningPlayer = null; } } @@ -717,158 +832,188 @@ public class TurtleBrain implements ITurtleAccess { * * @param nbt The tag to read from */ - private void readCommon(CompoundTag nbt) { + private void readCommon( CompoundTag nbt ) + { // Read fields - this.m_colourHex = nbt.contains(NBT_COLOUR) ? nbt.getInt(NBT_COLOUR) : -1; - this.m_fuelLevel = nbt.contains(NBT_FUEL) ? nbt.getInt(NBT_FUEL) : 0; - this.m_overlay = nbt.contains(NBT_OVERLAY) ? new Identifier(nbt.getString(NBT_OVERLAY)) : null; + this.m_colourHex = nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : -1; + this.m_fuelLevel = nbt.contains( NBT_FUEL ) ? nbt.getInt( NBT_FUEL ) : 0; + this.m_overlay = nbt.contains( NBT_OVERLAY ) ? new Identifier( nbt.getString( NBT_OVERLAY ) ) : null; // Read upgrades - this.setUpgrade(TurtleSide.LEFT, nbt.contains(NBT_LEFT_UPGRADE) ? TurtleUpgrades.get(nbt.getString(NBT_LEFT_UPGRADE)) : null); - this.setUpgrade(TurtleSide.RIGHT, nbt.contains(NBT_RIGHT_UPGRADE) ? TurtleUpgrades.get(nbt.getString(NBT_RIGHT_UPGRADE)) : null); + this.setUpgrade( TurtleSide.LEFT, nbt.contains( NBT_LEFT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_LEFT_UPGRADE ) ) : null ); + this.setUpgrade( TurtleSide.RIGHT, nbt.contains( NBT_RIGHT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_RIGHT_UPGRADE ) ) : null ); // NBT this.m_upgradeNBTData.clear(); - if (nbt.contains(NBT_LEFT_UPGRADE_DATA)) { - this.m_upgradeNBTData.put(TurtleSide.LEFT, - nbt.getCompound(NBT_LEFT_UPGRADE_DATA) - .copy()); + if( nbt.contains( NBT_LEFT_UPGRADE_DATA ) ) + { + this.m_upgradeNBTData.put( TurtleSide.LEFT, + nbt.getCompound( NBT_LEFT_UPGRADE_DATA ) + .copy() ); } - if (nbt.contains(NBT_RIGHT_UPGRADE_DATA)) { - this.m_upgradeNBTData.put(TurtleSide.RIGHT, - nbt.getCompound(NBT_RIGHT_UPGRADE_DATA) - .copy()); + if( nbt.contains( NBT_RIGHT_UPGRADE_DATA ) ) + { + this.m_upgradeNBTData.put( TurtleSide.RIGHT, + nbt.getCompound( NBT_RIGHT_UPGRADE_DATA ) + .copy() ); } } - public CompoundTag writeToNBT(CompoundTag nbt) { - this.writeCommon(nbt); + public CompoundTag writeToNBT( CompoundTag nbt ) + { + this.writeCommon( nbt ); // Write state - nbt.putInt(NBT_SLOT, this.m_selectedSlot); + nbt.putInt( NBT_SLOT, this.m_selectedSlot ); // Write owner - if (this.m_owningPlayer != null) { + if( this.m_owningPlayer != null ) + { CompoundTag owner = new CompoundTag(); - nbt.put("Owner", owner); + nbt.put( "Owner", owner ); - owner.putLong("UpperId", this.m_owningPlayer.getId() - .getMostSignificantBits()); - owner.putLong("LowerId", this.m_owningPlayer.getId() - .getLeastSignificantBits()); - owner.putString("Name", this.m_owningPlayer.getName()); + owner.putLong( "UpperId", this.m_owningPlayer.getId() + .getMostSignificantBits() ); + owner.putLong( "LowerId", this.m_owningPlayer.getId() + .getLeastSignificantBits() ); + owner.putString( "Name", this.m_owningPlayer.getName() ); } return nbt; } - private void writeCommon(CompoundTag nbt) { - nbt.putInt(NBT_FUEL, this.m_fuelLevel); - if (this.m_colourHex != -1) { - nbt.putInt(NBT_COLOUR, this.m_colourHex); + private void writeCommon( CompoundTag nbt ) + { + nbt.putInt( NBT_FUEL, this.m_fuelLevel ); + if( this.m_colourHex != -1 ) + { + nbt.putInt( NBT_COLOUR, this.m_colourHex ); } - if (this.m_overlay != null) { - nbt.putString(NBT_OVERLAY, this.m_overlay.toString()); + if( this.m_overlay != null ) + { + nbt.putString( NBT_OVERLAY, this.m_overlay.toString() ); } // Write upgrades - String leftUpgradeId = getUpgradeId(this.getUpgrade(TurtleSide.LEFT)); - if (leftUpgradeId != null) { - nbt.putString(NBT_LEFT_UPGRADE, leftUpgradeId); + String leftUpgradeId = getUpgradeId( this.getUpgrade( TurtleSide.LEFT ) ); + if( leftUpgradeId != null ) + { + nbt.putString( NBT_LEFT_UPGRADE, leftUpgradeId ); } - String rightUpgradeId = getUpgradeId(this.getUpgrade(TurtleSide.RIGHT)); - if (rightUpgradeId != null) { - nbt.putString(NBT_RIGHT_UPGRADE, rightUpgradeId); + String rightUpgradeId = getUpgradeId( this.getUpgrade( TurtleSide.RIGHT ) ); + if( rightUpgradeId != null ) + { + nbt.putString( NBT_RIGHT_UPGRADE, rightUpgradeId ); } // Write upgrade NBT - if (this.m_upgradeNBTData.containsKey(TurtleSide.LEFT)) { - nbt.put(NBT_LEFT_UPGRADE_DATA, - this.getUpgradeNBTData(TurtleSide.LEFT).copy()); + if( this.m_upgradeNBTData.containsKey( TurtleSide.LEFT ) ) + { + nbt.put( NBT_LEFT_UPGRADE_DATA, + this.getUpgradeNBTData( TurtleSide.LEFT ).copy() ); } - if (this.m_upgradeNBTData.containsKey(TurtleSide.RIGHT)) { - nbt.put(NBT_RIGHT_UPGRADE_DATA, - this.getUpgradeNBTData(TurtleSide.RIGHT).copy()); + if( this.m_upgradeNBTData.containsKey( TurtleSide.RIGHT ) ) + { + nbt.put( NBT_RIGHT_UPGRADE_DATA, + this.getUpgradeNBTData( TurtleSide.RIGHT ).copy() ); } } - private static String getUpgradeId(ITurtleUpgrade upgrade) { + private static String getUpgradeId( ITurtleUpgrade upgrade ) + { return upgrade != null ? upgrade.getUpgradeID() - .toString() : null; + .toString() : null; } - public void readDescription(CompoundTag nbt) { - this.readCommon(nbt); + public void readDescription( CompoundTag nbt ) + { + this.readCommon( nbt ); // Animation - TurtleAnimation anim = TurtleAnimation.values()[nbt.getInt("Animation")]; - if (anim != this.m_animation && anim != TurtleAnimation.WAIT && anim != TurtleAnimation.SHORT_WAIT && anim != TurtleAnimation.NONE) { + TurtleAnimation anim = TurtleAnimation.values()[nbt.getInt( "Animation" )]; + if( anim != this.m_animation && anim != TurtleAnimation.WAIT && anim != TurtleAnimation.SHORT_WAIT && anim != TurtleAnimation.NONE ) + { this.m_animation = anim; this.m_animationProgress = 0; this.m_lastAnimationProgress = 0; } } - public void writeDescription(CompoundTag nbt) { - this.writeCommon(nbt); - nbt.putInt("Animation", this.m_animation.ordinal()); + public void writeDescription( CompoundTag nbt ) + { + this.writeCommon( nbt ); + nbt.putInt( "Animation", this.m_animation.ordinal() ); } - public Identifier getOverlay() { + public Identifier getOverlay() + { return this.m_overlay; } - public void setOverlay(Identifier overlay) { - if (!Objects.equal(this.m_overlay, overlay)) { + public void setOverlay( Identifier overlay ) + { + if( !Objects.equal( this.m_overlay, overlay ) ) + { this.m_overlay = overlay; this.m_owner.updateBlock(); } } - public DyeColor getDyeColour() { - if (this.m_colourHex == -1) { + public DyeColor getDyeColour() + { + if( this.m_colourHex == -1 ) + { return null; } - Colour colour = Colour.fromHex(this.m_colourHex); - return colour == null ? null : DyeColor.byId(15 - colour.ordinal()); + Colour colour = Colour.fromHex( this.m_colourHex ); + return colour == null ? null : DyeColor.byId( 15 - colour.ordinal() ); } - public void setDyeColour(DyeColor dyeColour) { + public void setDyeColour( DyeColor dyeColour ) + { int newColour = -1; - if (dyeColour != null) { + if( dyeColour != null ) + { newColour = Colour.values()[15 - dyeColour.getId()].getHex(); } - if (this.m_colourHex != newColour) { + if( this.m_colourHex != newColour ) + { this.m_colourHex = newColour; this.m_owner.updateBlock(); } } - public float getToolRenderAngle(TurtleSide side, float f) { + public float getToolRenderAngle( TurtleSide side, float f ) + { return (side == TurtleSide.LEFT && this.m_animation == TurtleAnimation.SWING_LEFT_TOOL) || (side == TurtleSide.RIGHT && this.m_animation == TurtleAnimation.SWING_RIGHT_TOOL) ? 45.0f * (float) Math.sin( - this.getAnimationFraction(f) * Math.PI) : 0.0f; + this.getAnimationFraction( f ) * Math.PI ) : 0.0f; } - private static final class CommandCallback implements ILuaCallback { - final MethodResult pull = MethodResult.pullEvent("turtle_response", this); + private static final class CommandCallback implements ILuaCallback + { + final MethodResult pull = MethodResult.pullEvent( "turtle_response", this ); private final int command; - CommandCallback(int command) { + CommandCallback( int command ) + { this.command = command; } @Nonnull @Override - public MethodResult resume(Object[] response) { - if (response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean)) { + public MethodResult resume( Object[] response ) + { + if( response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean) ) + { return this.pull; } - if (((Number) response[1]).intValue() != this.command) { + if( ((Number) response[1]).intValue() != this.command ) + { return this.pull; } - return MethodResult.of(Arrays.copyOfRange(response, 2, response.length)); + return MethodResult.of( Arrays.copyOfRange( response, 2, response.length ) ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java index 80c40edb3..17f203329 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java @@ -8,11 +8,13 @@ package dan200.computercraft.shared.turtle.core; import dan200.computercraft.api.turtle.ITurtleCommand; -public class TurtleCommandQueueEntry { +public class TurtleCommandQueueEntry +{ public final int callbackID; public final ITurtleCommand command; - public TurtleCommandQueueEntry(int callbackID, ITurtleCommand command) { + public TurtleCommandQueueEntry( int callbackID, ITurtleCommand command ) + { this.callbackID = callbackID; this.command = command; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java index dcf60d2b8..69fb115d3 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java @@ -6,14 +6,9 @@ package dan200.computercraft.shared.turtle.core; -import java.util.List; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleCommandResult; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.item.ItemStack; @@ -22,40 +17,52 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class TurtleCompareCommand implements ITurtleCommand { +import javax.annotation.Nonnull; +import java.util.List; + +public class TurtleCompareCommand implements ITurtleCommand +{ private final InteractDirection m_direction; - public TurtleCompareCommand(InteractDirection direction) { + public TurtleCompareCommand( InteractDirection direction ) + { this.m_direction = direction; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Get world direction from direction - Direction direction = this.m_direction.toWorldDir(turtle); + Direction direction = this.m_direction.toWorldDir( turtle ); // Get currently selected stack ItemStack selectedStack = turtle.getInventory() - .getStack(turtle.getSelectedSlot()); + .getStack( turtle.getSelectedSlot() ); // Get stack representing thing in front World world = turtle.getWorld(); BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset(direction); + BlockPos newPosition = oldPosition.offset( direction ); ItemStack lookAtStack = ItemStack.EMPTY; - if (!world.isAir(newPosition)) { - BlockState lookAtState = world.getBlockState(newPosition); + if( !world.isAir( newPosition ) ) + { + BlockState lookAtState = world.getBlockState( newPosition ); Block lookAtBlock = lookAtState.getBlock(); - if (!lookAtState.isAir()) { + if( !lookAtState.isAir() ) + { // See if the block drops anything with the same ID as itself // (try 5 times to try and beat random number generators) - for (int i = 0; i < 5 && lookAtStack.isEmpty(); i++) { - List drops = Block.getDroppedStacks(lookAtState, (ServerWorld) world, newPosition, world.getBlockEntity(newPosition)); - if (!drops.isEmpty()) { - for (ItemStack drop : drops) { - if (drop.getItem() == lookAtBlock.asItem()) { + for( int i = 0; i < 5 && lookAtStack.isEmpty(); i++ ) + { + List drops = Block.getDroppedStacks( lookAtState, (ServerWorld) world, newPosition, world.getBlockEntity( newPosition ) ); + if( !drops.isEmpty() ) + { + for( ItemStack drop : drops ) + { + if( drop.getItem() == lookAtBlock.asItem() ) + { lookAtStack = drop; break; } @@ -64,8 +71,9 @@ public class TurtleCompareCommand implements ITurtleCommand { } // Last resort: roll our own (which will probably be wrong) - if (lookAtStack.isEmpty()) { - lookAtStack = new ItemStack(lookAtBlock); + if( lookAtStack.isEmpty() ) + { + lookAtStack = new ItemStack( lookAtBlock ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java index 139a06e34..c34cd8856 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java @@ -6,32 +6,37 @@ package dan200.computercraft.shared.turtle.core; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.shared.util.InventoryUtil; - import net.minecraft.item.ItemStack; -public class TurtleCompareToCommand implements ITurtleCommand { +import javax.annotation.Nonnull; + +public class TurtleCompareToCommand implements ITurtleCommand +{ private final int m_slot; - public TurtleCompareToCommand(int slot) { + public TurtleCompareToCommand( int slot ) + { this.m_slot = slot; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { ItemStack selectedStack = turtle.getInventory() - .getStack(turtle.getSelectedSlot()); + .getStack( turtle.getSelectedSlot() ); ItemStack stack = turtle.getInventory() - .getStack(this.m_slot); - if (InventoryUtil.areItemsStackable(selectedStack, stack)) { + .getStack( this.m_slot ); + if( InventoryUtil.areItemsStackable( selectedStack, stack ) ) + { return TurtleCommandResult.success(); - } else { + } + else + { return TurtleCommandResult.failure(); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java index 196a8bc5f..2cbfbedf4 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java @@ -6,10 +6,6 @@ package dan200.computercraft.shared.turtle.core; -import java.util.List; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; @@ -17,36 +13,45 @@ import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.shared.turtle.upgrades.TurtleInventoryCrafting; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.item.ItemStack; -public class TurtleCraftCommand implements ITurtleCommand { +import javax.annotation.Nonnull; +import java.util.List; + +public class TurtleCraftCommand implements ITurtleCommand +{ private final int limit; - public TurtleCraftCommand(int limit) { + public TurtleCraftCommand( int limit ) + { this.limit = limit; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Craft the item - TurtleInventoryCrafting crafting = new TurtleInventoryCrafting(turtle); - List results = crafting.doCrafting(turtle.getWorld(), this.limit); - if (results == null) { - return TurtleCommandResult.failure("No matching recipes"); + TurtleInventoryCrafting crafting = new TurtleInventoryCrafting( turtle ); + List results = crafting.doCrafting( turtle.getWorld(), this.limit ); + if( results == null ) + { + return TurtleCommandResult.failure( "No matching recipes" ); } // Store or drop any remainders - for (ItemStack stack : results) { - ItemStack remainder = InventoryUtil.storeItems(stack, turtle.getItemHandler(), turtle.getSelectedSlot()); - if (!remainder.isEmpty()) { - WorldUtil.dropItemStack(remainder, turtle.getWorld(), turtle.getPosition(), turtle.getDirection()); + for( ItemStack stack : results ) + { + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); + if( !remainder.isEmpty() ) + { + WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), turtle.getDirection() ); } } - if (!results.isEmpty()) { - turtle.playAnimation(TurtleAnimation.WAIT); + if( !results.isEmpty() ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); } return TurtleCommandResult.success(); } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java index 9d4e239ea..269bb9388 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java @@ -6,35 +6,37 @@ package dan200.computercraft.shared.turtle.core; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class TurtleDetectCommand implements ITurtleCommand { +import javax.annotation.Nonnull; + +public class TurtleDetectCommand implements ITurtleCommand +{ private final InteractDirection m_direction; - public TurtleDetectCommand(InteractDirection direction) { + public TurtleDetectCommand( InteractDirection direction ) + { this.m_direction = direction; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Get world direction from direction - Direction direction = this.m_direction.toWorldDir(turtle); + Direction direction = this.m_direction.toWorldDir( turtle ); // Check if thing in front is air or not World world = turtle.getWorld(); BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset(direction); + BlockPos newPosition = oldPosition.offset( direction ); - return !WorldUtil.isLiquidBlock(world, newPosition) && !world.isAir(newPosition) ? TurtleCommandResult.success() : TurtleCommandResult.failure(); + return !WorldUtil.isLiquidBlock( world, newPosition ) && !world.isAir( newPosition ) ? TurtleCommandResult.success() : TurtleCommandResult.failure(); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java index 5a0e000f7..611d63f1c 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java @@ -6,8 +6,6 @@ package dan200.computercraft.shared.turtle.core; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; @@ -17,76 +15,90 @@ import dan200.computercraft.api.turtle.event.TurtleInventoryEvent; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class TurtleDropCommand implements ITurtleCommand { +import javax.annotation.Nonnull; + +public class TurtleDropCommand implements ITurtleCommand +{ private final InteractDirection m_direction; private final int m_quantity; - public TurtleDropCommand(InteractDirection direction, int quantity) { + public TurtleDropCommand( InteractDirection direction, int quantity ) + { this.m_direction = direction; this.m_quantity = quantity; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Dropping nothing is easy - if (this.m_quantity == 0) { - turtle.playAnimation(TurtleAnimation.WAIT); + if( this.m_quantity == 0 ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); } // Get world direction from direction - Direction direction = this.m_direction.toWorldDir(turtle); + Direction direction = this.m_direction.toWorldDir( turtle ); // Get things to drop - ItemStack stack = InventoryUtil.takeItems(this.m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot()); - if (stack.isEmpty()) { - return TurtleCommandResult.failure("No items to drop"); + ItemStack stack = InventoryUtil.takeItems( this.m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + if( stack.isEmpty() ) + { + return TurtleCommandResult.failure( "No items to drop" ); } // Get inventory for thing in front World world = turtle.getWorld(); BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset(direction); + BlockPos newPosition = oldPosition.offset( direction ); Direction side = direction.getOpposite(); - Inventory inventory = InventoryUtil.getInventory(world, newPosition, side); + Inventory inventory = InventoryUtil.getInventory( world, newPosition, side ); // Fire the event, restoring the inventory and exiting if it is cancelled. - TurtlePlayer player = TurtlePlaceCommand.createPlayer(turtle, oldPosition, direction); - TurtleInventoryEvent.Drop event = new TurtleInventoryEvent.Drop(turtle, player, world, newPosition, inventory, stack); - if (TurtleEvent.post(event)) { - InventoryUtil.storeItems(stack, turtle.getItemHandler(), turtle.getSelectedSlot()); - return TurtleCommandResult.failure(event.getFailureMessage()); + TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); + TurtleInventoryEvent.Drop event = new TurtleInventoryEvent.Drop( turtle, player, world, newPosition, inventory, stack ); + if( TurtleEvent.post( event ) ) + { + InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); + return TurtleCommandResult.failure( event.getFailureMessage() ); } - if (inventory != null) { + if( inventory != null ) + { // Drop the item into the inventory - ItemStack remainder = InventoryUtil.storeItems(stack, ItemStorage.wrap(inventory, side)); - if (!remainder.isEmpty()) { + ItemStack remainder = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory, side ) ); + if( !remainder.isEmpty() ) + { // Put the remainder back in the turtle - InventoryUtil.storeItems(remainder, turtle.getItemHandler(), turtle.getSelectedSlot()); + InventoryUtil.storeItems( remainder, turtle.getItemHandler(), turtle.getSelectedSlot() ); } // Return true if we stored anything - if (remainder != stack) { - turtle.playAnimation(TurtleAnimation.WAIT); + if( remainder != stack ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); - } else { - return TurtleCommandResult.failure("No space for items"); } - } else { + else + { + return TurtleCommandResult.failure( "No space for items" ); + } + } + else + { // Drop the item into the world - WorldUtil.dropItemStack(stack, world, oldPosition, direction); - world.syncGlobalEvent(1000, newPosition, 0); - turtle.playAnimation(TurtleAnimation.WAIT); + WorldUtil.dropItemStack( stack, world, oldPosition, direction ); + world.syncGlobalEvent( 1000, newPosition, 0 ); + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java index eafe02ebe..b8455962a 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java @@ -6,14 +6,7 @@ package dan200.computercraft.shared.turtle.core; -import javax.annotation.Nonnull; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.api.turtle.*; import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.api.turtle.event.TurtleActionEvent; import dan200.computercraft.api.turtle.event.TurtleEvent; @@ -21,71 +14,87 @@ import dan200.computercraft.shared.TurtleUpgrades; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; -public class TurtleEquipCommand implements ITurtleCommand { +import javax.annotation.Nonnull; + +public class TurtleEquipCommand implements ITurtleCommand +{ private final TurtleSide m_side; - public TurtleEquipCommand(TurtleSide side) { + public TurtleEquipCommand( TurtleSide side ) + { this.m_side = side; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Determine the upgrade to equipLeft ITurtleUpgrade newUpgrade; ItemStack newUpgradeStack; Inventory inventory = turtle.getInventory(); - ItemStack selectedStack = inventory.getStack(turtle.getSelectedSlot()); - if (!selectedStack.isEmpty()) { + ItemStack selectedStack = inventory.getStack( turtle.getSelectedSlot() ); + if( !selectedStack.isEmpty() ) + { newUpgradeStack = selectedStack.copy(); - newUpgrade = TurtleUpgrades.get(newUpgradeStack); - if (newUpgrade == null || !TurtleUpgrades.suitableForFamily(((TurtleBrain) turtle).getFamily(), newUpgrade)) { - return TurtleCommandResult.failure("Not a valid upgrade"); + newUpgrade = TurtleUpgrades.get( newUpgradeStack ); + if( newUpgrade == null || !TurtleUpgrades.suitableForFamily( ((TurtleBrain) turtle).getFamily(), newUpgrade ) ) + { + return TurtleCommandResult.failure( "Not a valid upgrade" ); } - } else { + } + else + { newUpgradeStack = null; newUpgrade = null; } // Determine the upgrade to replace ItemStack oldUpgradeStack; - ITurtleUpgrade oldUpgrade = turtle.getUpgrade(this.m_side); - if (oldUpgrade != null) { + ITurtleUpgrade oldUpgrade = turtle.getUpgrade( this.m_side ); + if( oldUpgrade != null ) + { ItemStack craftingItem = oldUpgrade.getCraftingItem(); oldUpgradeStack = !craftingItem.isEmpty() ? craftingItem.copy() : null; - } else { + } + else + { oldUpgradeStack = null; } - TurtleActionEvent event = new TurtleActionEvent(turtle, TurtleAction.EQUIP); - if (TurtleEvent.post(event)) { - return TurtleCommandResult.failure(event.getFailureMessage()); + TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.EQUIP ); + if( TurtleEvent.post( event ) ) + { + return TurtleCommandResult.failure( event.getFailureMessage() ); } // Do the swapping: - if (newUpgradeStack != null) { + if( newUpgradeStack != null ) + { // Consume new upgrades item - InventoryUtil.takeItems(1, ItemStorage.wrap(inventory), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot()); + InventoryUtil.takeItems( 1, ItemStorage.wrap( inventory ), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); } - if (oldUpgradeStack != null) { + if( oldUpgradeStack != null ) + { // Store old upgrades item - ItemStack remainder = InventoryUtil.storeItems(oldUpgradeStack, ItemStorage.wrap(inventory), turtle.getSelectedSlot()); - if (!remainder.isEmpty()) { + ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, ItemStorage.wrap( inventory ), turtle.getSelectedSlot() ); + if( !remainder.isEmpty() ) + { // If there's no room for the items, drop them BlockPos position = turtle.getPosition(); - WorldUtil.dropItemStack(remainder, turtle.getWorld(), position, turtle.getDirection()); + WorldUtil.dropItemStack( remainder, turtle.getWorld(), position, turtle.getDirection() ); } } - turtle.setUpgrade(this.m_side, newUpgrade); + turtle.setUpgrade( this.m_side, newUpgrade ); // Animate - if (newUpgrade != null || oldUpgrade != null) { - turtle.playAnimation(TurtleAnimation.WAIT); + if( newUpgrade != null || oldUpgrade != null ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); } return TurtleCommandResult.success(); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java index 0249ba6bd..5e781b23a 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java @@ -6,70 +6,72 @@ package dan200.computercraft.shared.turtle.core; -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Nonnull; - -import com.google.common.collect.ImmutableMap; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.event.TurtleBlockEvent; import dan200.computercraft.api.turtle.event.TurtleEvent; - import dan200.computercraft.shared.peripheral.generic.data.BlockData; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.state.property.Property; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraft.util.registry.Registry; import net.minecraft.world.World; -public class TurtleInspectCommand implements ITurtleCommand { +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; + +public class TurtleInspectCommand implements ITurtleCommand +{ private final InteractDirection direction; - public TurtleInspectCommand(InteractDirection direction) { + public TurtleInspectCommand( InteractDirection direction ) + { this.direction = direction; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Get world direction from direction - Direction direction = this.direction.toWorldDir(turtle); + Direction direction = this.direction.toWorldDir( turtle ); // Check if thing in front is air or not World world = turtle.getWorld(); BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset(direction); + BlockPos newPosition = oldPosition.offset( direction ); - BlockState state = world.getBlockState(newPosition); - if (state.isAir()) { - return TurtleCommandResult.failure("No block to inspect"); + BlockState state = world.getBlockState( newPosition ); + if( state.isAir() ) + { + return TurtleCommandResult.failure( "No block to inspect" ); } Map table = BlockData.fill( new HashMap<>(), state ); // Fire the event, exiting if it is cancelled - TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer(turtle, oldPosition, direction); - TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect(turtle, turtlePlayer, world, newPosition, state, table); - if (TurtleEvent.post(event)) { - return TurtleCommandResult.failure(event.getFailureMessage()); + TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); + TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect( turtle, turtlePlayer, world, newPosition, state, table ); + if( TurtleEvent.post( event ) ) + { + return TurtleCommandResult.failure( event.getFailureMessage() ); } - return TurtleCommandResult.success(new Object[] {table}); + return TurtleCommandResult.success( new Object[] { table } ); } - @SuppressWarnings ({ + @SuppressWarnings( { "unchecked", "rawtypes" - }) - private static Object getPropertyValue(Property property, Comparable value) { - if (value instanceof String || value instanceof Number || value instanceof Boolean) { + } ) + private static Object getPropertyValue( Property property, Comparable value ) + { + if( value instanceof String || value instanceof Number || value instanceof Boolean ) + { return value; } - return property.name(value); + return property.name( value ); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java index 134dce9ca..a57bd841a 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java @@ -6,10 +6,6 @@ package dan200.computercraft.shared.turtle.core; -import java.util.List; - -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; @@ -19,7 +15,6 @@ import dan200.computercraft.api.turtle.event.TurtleBlockEvent; import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.shared.TurtlePermissions; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; @@ -29,120 +24,143 @@ import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.World; -public class TurtleMoveCommand implements ITurtleCommand { - private static final Box EMPTY_BOX = new Box(0, 0, 0, 0, 0, 0); +import javax.annotation.Nonnull; +import java.util.List; + +public class TurtleMoveCommand implements ITurtleCommand +{ + private static final Box EMPTY_BOX = new Box( 0, 0, 0, 0, 0, 0 ); private final MoveDirection m_direction; - public TurtleMoveCommand(MoveDirection direction) { + public TurtleMoveCommand( MoveDirection direction ) + { this.m_direction = direction; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Get world direction from direction - Direction direction = this.m_direction.toWorldDir(turtle); + Direction direction = this.m_direction.toWorldDir( turtle ); // Check if we can move World oldWorld = turtle.getWorld(); BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset(direction); + BlockPos newPosition = oldPosition.offset( direction ); - TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer(turtle, oldPosition, direction); - TurtleCommandResult canEnterResult = canEnter(turtlePlayer, oldWorld, newPosition); - if (!canEnterResult.isSuccess()) { + TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); + TurtleCommandResult canEnterResult = canEnter( turtlePlayer, oldWorld, newPosition ); + if( !canEnterResult.isSuccess() ) + { return canEnterResult; } // Check existing block is air or replaceable - BlockState state = oldWorld.getBlockState(newPosition); - if (!oldWorld.isAir(newPosition) && !WorldUtil.isLiquidBlock(oldWorld, newPosition) && !state.getMaterial() - .isReplaceable()) { - return TurtleCommandResult.failure("Movement obstructed"); + BlockState state = oldWorld.getBlockState( newPosition ); + if( !oldWorld.isAir( newPosition ) && !WorldUtil.isLiquidBlock( oldWorld, newPosition ) && !state.getMaterial() + .isReplaceable() ) + { + return TurtleCommandResult.failure( "Movement obstructed" ); } // Check there isn't anything in the way - VoxelShape collision = state.getCollisionShape(oldWorld, oldPosition) - .offset(newPosition.getX(), newPosition.getY(), newPosition.getZ()); + VoxelShape collision = state.getCollisionShape( oldWorld, oldPosition ) + .offset( newPosition.getX(), newPosition.getY(), newPosition.getZ() ); - if (!oldWorld.intersectsEntities(null, collision)) { - if (!ComputerCraft.turtlesCanPush || this.m_direction == MoveDirection.UP || this.m_direction == MoveDirection.DOWN) { - return TurtleCommandResult.failure("Movement obstructed"); + if( !oldWorld.intersectsEntities( null, collision ) ) + { + if( !ComputerCraft.turtlesCanPush || this.m_direction == MoveDirection.UP || this.m_direction == MoveDirection.DOWN ) + { + return TurtleCommandResult.failure( "Movement obstructed" ); } // Check there is space for all the pushable entities to be pushed - List list = oldWorld.getEntitiesByClass(Entity.class, getBox(collision), x -> x != null && x.isAlive() && x.inanimate); - for (Entity entity : list) { + List list = oldWorld.getEntitiesByClass( Entity.class, getBox( collision ), x -> x != null && x.isAlive() && x.inanimate ); + for( Entity entity : list ) + { Box pushedBB = entity.getBoundingBox() - .offset(direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ()); - if (!oldWorld.intersectsEntities(null, VoxelShapes.cuboid(pushedBB))) { - return TurtleCommandResult.failure("Movement obstructed"); + .offset( direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ() ); + if( !oldWorld.intersectsEntities( null, VoxelShapes.cuboid( pushedBB ) ) ) + { + return TurtleCommandResult.failure( "Movement obstructed" ); } } } - TurtleBlockEvent.Move moveEvent = new TurtleBlockEvent.Move(turtle, turtlePlayer, oldWorld, newPosition); - if (TurtleEvent.post(moveEvent)) { - return TurtleCommandResult.failure(moveEvent.getFailureMessage()); + TurtleBlockEvent.Move moveEvent = new TurtleBlockEvent.Move( turtle, turtlePlayer, oldWorld, newPosition ); + if( TurtleEvent.post( moveEvent ) ) + { + return TurtleCommandResult.failure( moveEvent.getFailureMessage() ); } // Check fuel level - if (turtle.isFuelNeeded() && turtle.getFuelLevel() < 1) { - return TurtleCommandResult.failure("Out of fuel"); + if( turtle.isFuelNeeded() && turtle.getFuelLevel() < 1 ) + { + return TurtleCommandResult.failure( "Out of fuel" ); } // Move - if (!turtle.teleportTo(oldWorld, newPosition)) { - return TurtleCommandResult.failure("Movement failed"); + if( !turtle.teleportTo( oldWorld, newPosition ) ) + { + return TurtleCommandResult.failure( "Movement failed" ); } // Consume fuel - turtle.consumeFuel(1); + turtle.consumeFuel( 1 ); // Animate - switch (this.m_direction) { - case FORWARD: - default: - turtle.playAnimation(TurtleAnimation.MOVE_FORWARD); - break; - case BACK: - turtle.playAnimation(TurtleAnimation.MOVE_BACK); - break; - case UP: - turtle.playAnimation(TurtleAnimation.MOVE_UP); - break; - case DOWN: - turtle.playAnimation(TurtleAnimation.MOVE_DOWN); - break; + switch( this.m_direction ) + { + case FORWARD: + default: + turtle.playAnimation( TurtleAnimation.MOVE_FORWARD ); + break; + case BACK: + turtle.playAnimation( TurtleAnimation.MOVE_BACK ); + break; + case UP: + turtle.playAnimation( TurtleAnimation.MOVE_UP ); + break; + case DOWN: + turtle.playAnimation( TurtleAnimation.MOVE_DOWN ); + break; } return TurtleCommandResult.success(); } - private static TurtleCommandResult canEnter(TurtlePlayer turtlePlayer, World world, BlockPos position) { - if (World.isOutOfBuildLimitVertically(position)) { - return TurtleCommandResult.failure(position.getY() < 0 ? "Too low to move" : "Too high to move"); + private static TurtleCommandResult canEnter( TurtlePlayer turtlePlayer, World world, BlockPos position ) + { + if( World.isOutOfBuildLimitVertically( position ) ) + { + return TurtleCommandResult.failure( position.getY() < 0 ? "Too low to move" : "Too high to move" ); } - if (!World.isInBuildLimit(position)) { - return TurtleCommandResult.failure("Cannot leave the world"); + if( !World.isInBuildLimit( position ) ) + { + return TurtleCommandResult.failure( "Cannot leave the world" ); } // Check spawn protection - if (ComputerCraft.turtlesObeyBlockProtection && !TurtlePermissions.isBlockEnterable(world, position, turtlePlayer)) { - return TurtleCommandResult.failure("Cannot enter protected area"); + if( ComputerCraft.turtlesObeyBlockProtection && !TurtlePermissions.isBlockEnterable( world, position, turtlePlayer ) ) + { + return TurtleCommandResult.failure( "Cannot enter protected area" ); } - if (!world.isChunkLoaded(position)) { - return TurtleCommandResult.failure("Cannot leave loaded world"); + if( !world.isChunkLoaded( position ) ) + { + return TurtleCommandResult.failure( "Cannot leave loaded world" ); } - if (!world.getWorldBorder() - .contains(position)) { - return TurtleCommandResult.failure("Cannot pass the world border"); + if( !world.getWorldBorder() + .contains( position ) ) + { + return TurtleCommandResult.failure( "Cannot pass the world border" ); } return TurtleCommandResult.success(); } - private static Box getBox(VoxelShape shape) { + private static Box getBox( VoxelShape shape ) + { return shape.isEmpty() ? EMPTY_BOX : shape.getBoundingBox(); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java index d30264751..9817d650e 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -6,10 +6,6 @@ package dan200.computercraft.shared.turtle.core; -import java.util.List; - -import javax.annotation.Nonnull; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; @@ -22,14 +18,12 @@ import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.DropConsumer; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.item.*; -import org.apache.commons.lang3.tuple.Pair; - import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.item.*; import net.minecraft.text.LiteralText; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -39,147 +33,177 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import org.apache.commons.lang3.tuple.Pair; -public class TurtlePlaceCommand implements ITurtleCommand { +import javax.annotation.Nonnull; +import java.util.List; + +public class TurtlePlaceCommand implements ITurtleCommand +{ private final InteractDirection m_direction; private final Object[] m_extraArguments; - public TurtlePlaceCommand(InteractDirection direction, Object[] arguments) { + public TurtlePlaceCommand( InteractDirection direction, Object[] arguments ) + { this.m_direction = direction; this.m_extraArguments = arguments; } - public static ItemStack deploy(@Nonnull ItemStack stack, ITurtleAccess turtle, Direction direction, Object[] extraArguments, String[] outErrorMessage) { + public static ItemStack deploy( @Nonnull ItemStack stack, ITurtleAccess turtle, Direction direction, Object[] extraArguments, String[] outErrorMessage ) + { // Create a fake player, and orient it appropriately BlockPos playerPosition = turtle.getPosition() - .offset(direction); - TurtlePlayer turtlePlayer = createPlayer(turtle, playerPosition, direction); + .offset( direction ); + TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction ); - return deploy(stack, turtle, turtlePlayer, direction, extraArguments, outErrorMessage); + return deploy( stack, turtle, turtlePlayer, direction, extraArguments, outErrorMessage ); } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Get thing to place ItemStack stack = turtle.getInventory() - .getStack(turtle.getSelectedSlot()); - if (stack.isEmpty()) { - return TurtleCommandResult.failure("No items to place"); + .getStack( turtle.getSelectedSlot() ); + if( stack.isEmpty() ) + { + return TurtleCommandResult.failure( "No items to place" ); } // Remember old block - Direction direction = this.m_direction.toWorldDir(turtle); + Direction direction = this.m_direction.toWorldDir( turtle ); BlockPos coordinates = turtle.getPosition() - .offset(direction); + .offset( direction ); // Create a fake player, and orient it appropriately BlockPos playerPosition = turtle.getPosition() - .offset(direction); - TurtlePlayer turtlePlayer = createPlayer(turtle, playerPosition, direction); + .offset( direction ); + TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction ); - TurtleBlockEvent.Place place = new TurtleBlockEvent.Place(turtle, turtlePlayer, turtle.getWorld(), coordinates, stack); - if (TurtleEvent.post(place)) { - return TurtleCommandResult.failure(place.getFailureMessage()); + TurtleBlockEvent.Place place = new TurtleBlockEvent.Place( turtle, turtlePlayer, turtle.getWorld(), coordinates, stack ); + if( TurtleEvent.post( place ) ) + { + return TurtleCommandResult.failure( place.getFailureMessage() ); } // Do the deploying String[] errorMessage = new String[1]; - ItemStack remainder = deploy(stack, turtle, turtlePlayer, direction, this.m_extraArguments, errorMessage); - if (remainder != stack) { + ItemStack remainder = deploy( stack, turtle, turtlePlayer, direction, this.m_extraArguments, errorMessage ); + if( remainder != stack ) + { // Put the remaining items back turtle.getInventory() - .setStack(turtle.getSelectedSlot(), remainder); + .setStack( turtle.getSelectedSlot(), remainder ); turtle.getInventory() - .markDirty(); + .markDirty(); // Animate and return success - turtle.playAnimation(TurtleAnimation.WAIT); + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); - } else { - if (errorMessage[0] != null) { - return TurtleCommandResult.failure(errorMessage[0]); - } else if (stack.getItem() instanceof BlockItem) { - return TurtleCommandResult.failure("Cannot place block here"); - } else { - return TurtleCommandResult.failure("Cannot place item here"); + } + else + { + if( errorMessage[0] != null ) + { + return TurtleCommandResult.failure( errorMessage[0] ); + } + else if( stack.getItem() instanceof BlockItem ) + { + return TurtleCommandResult.failure( "Cannot place block here" ); + } + else + { + return TurtleCommandResult.failure( "Cannot place item here" ); } } } - public static TurtlePlayer createPlayer(ITurtleAccess turtle, BlockPos position, Direction direction) { - TurtlePlayer turtlePlayer = TurtlePlayer.get(turtle); - orientPlayer(turtle, turtlePlayer, position, direction); + public static TurtlePlayer createPlayer( ITurtleAccess turtle, BlockPos position, Direction direction ) + { + TurtlePlayer turtlePlayer = TurtlePlayer.get( turtle ); + orientPlayer( turtle, turtlePlayer, position, direction ); return turtlePlayer; } - public static ItemStack deploy(@Nonnull ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction, - Object[] extraArguments, String[] outErrorMessage) { + public static ItemStack deploy( @Nonnull ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction, + Object[] extraArguments, String[] outErrorMessage ) + { // Deploy on an entity - ItemStack remainder = deployOnEntity(stack, turtle, turtlePlayer, direction, extraArguments, outErrorMessage); - if (remainder != stack) { + ItemStack remainder = deployOnEntity( stack, turtle, turtlePlayer, direction, extraArguments, outErrorMessage ); + if( remainder != stack ) + { return remainder; } // Deploy on the block immediately in front BlockPos position = turtle.getPosition(); - BlockPos newPosition = position.offset(direction); - remainder = deployOnBlock(stack, turtle, turtlePlayer, newPosition, direction.getOpposite(), extraArguments, true, outErrorMessage); - if (remainder != stack) { + BlockPos newPosition = position.offset( direction ); + remainder = deployOnBlock( stack, turtle, turtlePlayer, newPosition, direction.getOpposite(), extraArguments, true, outErrorMessage ); + if( remainder != stack ) + { return remainder; } // Deploy on the block one block away - remainder = deployOnBlock(stack, - turtle, - turtlePlayer, - newPosition.offset(direction), - direction.getOpposite(), - extraArguments, - false, - outErrorMessage); - if (remainder != stack) { + remainder = deployOnBlock( stack, + turtle, + turtlePlayer, + newPosition.offset( direction ), + direction.getOpposite(), + extraArguments, + false, + outErrorMessage ); + if( remainder != stack ) + { return remainder; } - if (direction.getAxis() != Direction.Axis.Y) { + if( direction.getAxis() != Direction.Axis.Y ) + { // Deploy down on the block in front - remainder = deployOnBlock(stack, turtle, turtlePlayer, newPosition.down(), Direction.UP, extraArguments, false, outErrorMessage); - if (remainder != stack) { + remainder = deployOnBlock( stack, turtle, turtlePlayer, newPosition.down(), Direction.UP, extraArguments, false, outErrorMessage ); + if( remainder != stack ) + { return remainder; } } // Deploy back onto the turtle - remainder = deployOnBlock(stack, turtle, turtlePlayer, position, direction, extraArguments, false, outErrorMessage); + remainder = deployOnBlock( stack, turtle, turtlePlayer, position, direction, extraArguments, false, outErrorMessage ); return remainder; // If nothing worked, return the original stack unchanged } - private static void orientPlayer(ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction direction) { + private static void orientPlayer( ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction direction ) + { double posX = position.getX() + 0.5; double posY = position.getY() + 0.5; double posZ = position.getZ() + 0.5; // Stop intersection with the turtle itself - if (turtle.getPosition() - .equals(position)) { + if( turtle.getPosition() + .equals( position ) ) + { posX += 0.48 * direction.getOffsetX(); posY += 0.48 * direction.getOffsetY(); posZ += 0.48 * direction.getOffsetZ(); } - if (direction.getAxis() != Direction.Axis.Y) { + if( direction.getAxis() != Direction.Axis.Y ) + { turtlePlayer.yaw = direction.asRotation(); turtlePlayer.pitch = 0.0f; - } else { + } + else + { turtlePlayer.yaw = turtle.getDirection() - .asRotation(); - turtlePlayer.pitch = DirectionUtil.toPitchAngle(direction); + .asRotation(); + turtlePlayer.pitch = DirectionUtil.toPitchAngle( direction ); } - turtlePlayer.setPos(posX, posY, posZ); + turtlePlayer.setPos( posX, posY, posZ ); turtlePlayer.prevX = posX; turtlePlayer.prevY = posY; turtlePlayer.prevZ = posZ; @@ -191,90 +215,105 @@ public class TurtlePlaceCommand implements ITurtleCommand { } @Nonnull - private static ItemStack deployOnEntity(@Nonnull ItemStack stack, final ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction, - Object[] extraArguments, String[] outErrorMessage) { + private static ItemStack deployOnEntity( @Nonnull ItemStack stack, final ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction, + Object[] extraArguments, String[] outErrorMessage ) + { // See if there is an entity present final World world = turtle.getWorld(); final BlockPos position = turtle.getPosition(); Vec3d turtlePos = turtlePlayer.getPos(); - Vec3d rayDir = turtlePlayer.getRotationVec(1.0f); - Pair hit = WorldUtil.rayTraceEntities(world, turtlePos, rayDir, 1.5); - if (hit == null) { + Vec3d rayDir = turtlePlayer.getRotationVec( 1.0f ); + Pair hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 ); + if( hit == null ) + { return stack; } // Load up the turtle's inventory ItemStack stackCopy = stack.copy(); - turtlePlayer.loadInventory(stackCopy); + turtlePlayer.loadInventory( stackCopy ); // Start claiming entity drops Entity hitEntity = hit.getKey(); Vec3d hitPos = hit.getValue(); - DropConsumer.set(hitEntity, drop -> InventoryUtil.storeItems(drop, turtle.getItemHandler(), turtle.getSelectedSlot())); + DropConsumer.set( hitEntity, drop -> InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ) ); // Place on the entity boolean placed = false; - ActionResult cancelResult = hitEntity.interactAt(turtlePlayer, hitPos, Hand.MAIN_HAND); + ActionResult cancelResult = hitEntity.interactAt( turtlePlayer, hitPos, Hand.MAIN_HAND ); - if (cancelResult != null && cancelResult.isAccepted()) { + if( cancelResult != null && cancelResult.isAccepted() ) + { placed = true; } - else { - cancelResult = hitEntity.interact(turtlePlayer, Hand.MAIN_HAND); - if (cancelResult != null && cancelResult.isAccepted()) { + else + { + cancelResult = hitEntity.interact( turtlePlayer, Hand.MAIN_HAND ); + if( cancelResult != null && cancelResult.isAccepted() ) + { placed = true; } - else if (hitEntity instanceof LivingEntity) { - placed = stackCopy.useOnEntity(turtlePlayer, (LivingEntity) hitEntity, Hand.MAIN_HAND).isAccepted(); - if (placed) turtlePlayer.loadInventory(stackCopy); + else if( hitEntity instanceof LivingEntity ) + { + placed = stackCopy.useOnEntity( turtlePlayer, (LivingEntity) hitEntity, Hand.MAIN_HAND ).isAccepted(); + if( placed ) turtlePlayer.loadInventory( stackCopy ); } } // Stop claiming drops List remainingDrops = DropConsumer.clear(); - for (ItemStack remaining : remainingDrops) { - WorldUtil.dropItemStack(remaining, - world, - position, - turtle.getDirection() - .getOpposite()); + for( ItemStack remaining : remainingDrops ) + { + WorldUtil.dropItemStack( remaining, + world, + position, + turtle.getDirection() + .getOpposite() ); } // Put everything we collected into the turtles inventory, then return - ItemStack remainder = turtlePlayer.unloadInventory(turtle); - if (!placed && ItemStack.areEqual(stack, remainder)) { + ItemStack remainder = turtlePlayer.unloadInventory( turtle ); + if( !placed && ItemStack.areEqual( stack, remainder ) ) + { return stack; - } else if (!remainder.isEmpty()) { + } + else if( !remainder.isEmpty() ) + { return remainder; - } else { + } + else + { return ItemStack.EMPTY; } } @Nonnull - private static ItemStack deployOnBlock(@Nonnull ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction side, - Object[] extraArguments, boolean allowReplace, String[] outErrorMessage) { + private static ItemStack deployOnBlock( @Nonnull ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction side, + Object[] extraArguments, boolean allowReplace, String[] outErrorMessage ) + { // Re-orient the fake player Direction playerDir = side.getOpposite(); - BlockPos playerPosition = position.offset(side); - orientPlayer(turtle, turtlePlayer, playerPosition, playerDir); + BlockPos playerPosition = position.offset( side ); + orientPlayer( turtle, turtlePlayer, playerPosition, playerDir ); ItemStack stackCopy = stack.copy(); - turtlePlayer.loadInventory(stackCopy); + turtlePlayer.loadInventory( stackCopy ); // Calculate where the turtle would hit the block float hitX = 0.5f + side.getOffsetX() * 0.5f; float hitY = 0.5f + side.getOffsetY() * 0.5f; float hitZ = 0.5f + side.getOffsetZ() * 0.5f; - if (Math.abs(hitY - 0.5f) < 0.01f) { + if( Math.abs( hitY - 0.5f ) < 0.01f ) + { hitY = 0.45f; } // Check if there's something suitable to place onto - BlockHitResult hit = new BlockHitResult(new Vec3d(hitX, hitY, hitZ), side, position, false); - ItemUsageContext context = new ItemUsageContext(turtlePlayer, Hand.MAIN_HAND, hit); - ItemPlacementContext placementContext = new ItemPlacementContext(context); - if (!canDeployOnBlock(new ItemPlacementContext(context), turtle, turtlePlayer, position, side, allowReplace, outErrorMessage)) { + BlockHitResult hit = new BlockHitResult( new Vec3d( hitX, hitY, hitZ ), side, position, false ); + ItemUsageContext context = new ItemUsageContext( turtlePlayer, Hand.MAIN_HAND, hit ); + ItemPlacementContext placementContext = new ItemPlacementContext( context ); + if( !canDeployOnBlock( new ItemPlacementContext( context ), turtle, turtlePlayer, position, side, allowReplace, outErrorMessage ) ) + { return stack; } @@ -284,87 +323,112 @@ public class TurtlePlaceCommand implements ITurtleCommand { // Do the deploying (put everything in the players inventory) boolean placed = false; BlockEntity existingTile = turtle.getWorld() - .getBlockEntity(position); + .getBlockEntity( position ); - if (stackCopy.useOnBlock(context).isAccepted()) { + if( stackCopy.useOnBlock( context ).isAccepted() ) + { placed = true; - turtlePlayer.loadInventory(stackCopy); + turtlePlayer.loadInventory( stackCopy ); } - if (!placed && (item instanceof BucketItem || item instanceof BoatItem || item instanceof LilyPadItem || item instanceof GlassBottleItem)) { - TypedActionResult result = stackCopy.use(turtle.getWorld(), turtlePlayer, Hand.MAIN_HAND); - if (result.getResult() - .isAccepted() && !ItemStack.areEqual(stack, result.getValue())) { + if( !placed && (item instanceof BucketItem || item instanceof BoatItem || item instanceof LilyPadItem || item instanceof GlassBottleItem) ) + { + TypedActionResult result = stackCopy.use( turtle.getWorld(), turtlePlayer, Hand.MAIN_HAND ); + if( result.getResult() + .isAccepted() && !ItemStack.areEqual( stack, result.getValue() ) ) + { placed = true; - turtlePlayer.loadInventory(result.getValue()); + turtlePlayer.loadInventory( result.getValue() ); } } // Set text on signs - if (placed && item instanceof SignItem) { - if (extraArguments != null && extraArguments.length >= 1 && extraArguments[0] instanceof String) { + if( placed && item instanceof SignItem ) + { + if( extraArguments != null && extraArguments.length >= 1 && extraArguments[0] instanceof String ) + { World world = turtle.getWorld(); - BlockEntity tile = world.getBlockEntity(position); - if (tile == null || tile == existingTile) { - tile = world.getBlockEntity(position.offset(side)); + BlockEntity tile = world.getBlockEntity( position ); + if( tile == null || tile == existingTile ) + { + tile = world.getBlockEntity( position.offset( side ) ); } - if (tile instanceof SignBlockEntity) { + if( tile instanceof SignBlockEntity ) + { SignBlockEntity signTile = (SignBlockEntity) tile; String s = (String) extraArguments[0]; - String[] split = s.split("\n"); + String[] split = s.split( "\n" ); int firstLine = split.length <= 2 ? 1 : 0; - for (int i = 0; i < 4; i++) { - if (i >= firstLine && i < firstLine + split.length) { - if (split[i - firstLine].length() > 15) { - signTile.setTextOnRow(i, new LiteralText(split[i - firstLine].substring(0, 15))); - } else { - signTile.setTextOnRow(i, new LiteralText(split[i - firstLine])); + for( int i = 0; i < 4; i++ ) + { + if( i >= firstLine && i < firstLine + split.length ) + { + if( split[i - firstLine].length() > 15 ) + { + signTile.setTextOnRow( i, new LiteralText( split[i - firstLine].substring( 0, 15 ) ) ); } - } else { - signTile.setTextOnRow(i, new LiteralText("")); + else + { + signTile.setTextOnRow( i, new LiteralText( split[i - firstLine] ) ); + } + } + else + { + signTile.setTextOnRow( i, new LiteralText( "" ) ); } } signTile.markDirty(); - world.updateListeners(tile.getPos(), tile.getCachedState(), tile.getCachedState(), 3); + world.updateListeners( tile.getPos(), tile.getCachedState(), tile.getCachedState(), 3 ); } } } // Put everything we collected into the turtles inventory, then return - ItemStack remainder = turtlePlayer.unloadInventory(turtle); - if (!placed && ItemStack.areEqual(stack, remainder)) { + ItemStack remainder = turtlePlayer.unloadInventory( turtle ); + if( !placed && ItemStack.areEqual( stack, remainder ) ) + { return stack; - } else if (!remainder.isEmpty()) { + } + else if( !remainder.isEmpty() ) + { return remainder; - } else { + } + else + { return ItemStack.EMPTY; } } - private static boolean canDeployOnBlock(@Nonnull ItemPlacementContext context, ITurtleAccess turtle, TurtlePlayer player, BlockPos position, - Direction side, boolean allowReplaceable, String[] outErrorMessage) { + private static boolean canDeployOnBlock( @Nonnull ItemPlacementContext context, ITurtleAccess turtle, TurtlePlayer player, BlockPos position, + Direction side, boolean allowReplaceable, String[] outErrorMessage ) + { World world = turtle.getWorld(); - if (!World.isInBuildLimit(position) || world.isAir(position) || (context.getStack() - .getItem() instanceof BlockItem && WorldUtil.isLiquidBlock(world, - position))) { + if( !World.isInBuildLimit( position ) || world.isAir( position ) || (context.getStack() + .getItem() instanceof BlockItem && WorldUtil.isLiquidBlock( world, + position )) ) + { return false; } - BlockState state = world.getBlockState(position); + BlockState state = world.getBlockState( position ); - boolean replaceable = state.canReplace(context); - if (!allowReplaceable && replaceable) { + boolean replaceable = state.canReplace( context ); + if( !allowReplaceable && replaceable ) + { return false; } - if (ComputerCraft.turtlesObeyBlockProtection) { + if( ComputerCraft.turtlesObeyBlockProtection ) + { // Check spawn protection - boolean editable = replaceable ? TurtlePermissions.isBlockEditable(world, position, player) : TurtlePermissions.isBlockEditable(world, - position.offset( - side), - player); - if (!editable) { - if (outErrorMessage != null) { + boolean editable = replaceable ? TurtlePermissions.isBlockEditable( world, position, player ) : TurtlePermissions.isBlockEditable( world, + position.offset( + side ), + player ); + if( !editable ) + { + if( outErrorMessage != null ) + { outErrorMessage[0] = "Cannot place in protected area"; } return false; diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java index 52d2259b8..5ec609d09 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java @@ -6,12 +6,6 @@ package dan200.computercraft.shared.turtle.core; -import java.util.OptionalInt; -import java.util.UUID; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.mojang.authlib.GameProfile; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.FakePlayer; @@ -20,7 +14,6 @@ import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.util.FakeNetHandler; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.WorldUtil; - import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; @@ -31,17 +24,24 @@ import net.minecraft.entity.passive.HorseBaseEntity; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.server.world.ServerWorld; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -@SuppressWarnings ("EntityConstructor") -public final class TurtlePlayer extends FakePlayer { - private static final GameProfile DEFAULT_PROFILE = new GameProfile(UUID.fromString("0d0c4ca0-4ff1-11e4-916c-0800200c9a66"), "[ComputerCraft]"); -// TODO [M3R1-01] Fix Turtle not giving player achievement for actions +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.OptionalInt; +import java.util.UUID; + +@SuppressWarnings( "EntityConstructor" ) +public final class TurtlePlayer extends FakePlayer +{ + private static final GameProfile DEFAULT_PROFILE = new GameProfile( UUID.fromString( "0d0c4ca0-4ff1-11e4-916c-0800200c9a66" ), "[ComputerCraft]" ); + + // TODO [M3R1-01] Fix Turtle not giving player achievement for actions private TurtlePlayer( ServerWorld world, GameProfile name ) { super( world, name ); @@ -61,70 +61,82 @@ public final class TurtlePlayer extends FakePlayer { // Constructing a player overrides the "active player" variable in advancements. As fake players cannot // get advancements, this prevents a normal player who has placed a turtle from getting advancements. // We try to locate the "actual" player and restore them. - ServerPlayerEntity actualPlayer = world.getServer().getPlayerManager().getPlayer(player.getUuid()); - if( actualPlayer != null ) player.getAdvancementTracker().setOwner(actualPlayer); + ServerPlayerEntity actualPlayer = world.getServer().getPlayerManager().getPlayer( player.getUuid() ); + if( actualPlayer != null ) player.getAdvancementTracker().setOwner( actualPlayer ); } return player; - } + } - private static GameProfile getProfile(@Nullable GameProfile profile) { + private static GameProfile getProfile( @Nullable GameProfile profile ) + { return profile != null && profile.isComplete() ? profile : DEFAULT_PROFILE; } - private void setState(ITurtleAccess turtle) { - if (this.currentScreenHandler != playerScreenHandler) { - ComputerCraft.log.warn("Turtle has open container ({})", this.currentScreenHandler); + private void setState( ITurtleAccess turtle ) + { + if( this.currentScreenHandler != playerScreenHandler ) + { + ComputerCraft.log.warn( "Turtle has open container ({})", this.currentScreenHandler ); closeHandledScreen(); } BlockPos position = turtle.getPosition(); - this.setPos(position.getX() + 0.5, position.getY() + 0.5, position.getZ() + 0.5); + this.setPos( position.getX() + 0.5, position.getY() + 0.5, position.getZ() + 0.5 ); this.yaw = turtle.getDirection() - .asRotation(); + .asRotation(); this.pitch = 0.0f; this.inventory.clear(); } - public static TurtlePlayer get(ITurtleAccess access) { + public static TurtlePlayer get( ITurtleAccess access ) + { if( !(access instanceof TurtleBrain) ) return create( access ); TurtleBrain brain = (TurtleBrain) access; TurtlePlayer player = brain.m_cachedPlayer; - if (player == null || player.getGameProfile() != getProfile(access.getOwningPlayer()) || player.getEntityWorld() != access.getWorld()) { - player = brain.m_cachedPlayer = create(brain); - } else { - player.setState(access); + if( player == null || player.getGameProfile() != getProfile( access.getOwningPlayer() ) || player.getEntityWorld() != access.getWorld() ) + { + player = brain.m_cachedPlayer = create( brain ); + } + else + { + player.setState( access ); } return player; } - public void loadInventory(@Nonnull ItemStack currentStack) { + public void loadInventory( @Nonnull ItemStack currentStack ) + { // Load up the fake inventory this.inventory.selectedSlot = 0; - this.inventory.setStack(0, currentStack); + this.inventory.setStack( 0, currentStack ); } - public ItemStack unloadInventory(ITurtleAccess turtle) { + public ItemStack unloadInventory( ITurtleAccess turtle ) + { // Get the item we placed with - ItemStack results = this.inventory.getStack(0); - this.inventory.setStack(0, ItemStack.EMPTY); + ItemStack results = this.inventory.getStack( 0 ); + this.inventory.setStack( 0, ItemStack.EMPTY ); // Store (or drop) anything else we found BlockPos dropPosition = turtle.getPosition(); Direction dropDirection = turtle.getDirection() - .getOpposite(); - for (int i = 0; i < this.inventory.size(); i++) { - ItemStack stack = this.inventory.getStack(i); - if (!stack.isEmpty()) { - ItemStack remainder = InventoryUtil.storeItems(stack, turtle.getItemHandler(), turtle.getSelectedSlot()); - if (!remainder.isEmpty()) { - WorldUtil.dropItemStack(remainder, turtle.getWorld(), dropPosition, dropDirection); + .getOpposite(); + for( int i = 0; i < this.inventory.size(); i++ ) + { + ItemStack stack = this.inventory.getStack( i ); + if( !stack.isEmpty() ) + { + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); + if( !remainder.isEmpty() ) + { + WorldUtil.dropItemStack( remainder, turtle.getWorld(), dropPosition, dropDirection ); } - this.inventory.setStack(i, ItemStack.EMPTY); + this.inventory.setStack( i, ItemStack.EMPTY ); } } this.inventory.markDirty(); @@ -133,79 +145,96 @@ public final class TurtlePlayer extends FakePlayer { @Nonnull @Override - public EntityType getType() { + public EntityType getType() + { return ComputerCraftRegistry.ModEntities.TURTLE_PLAYER; } @Override - public float getEyeHeight(@Nonnull EntityPose pose) { + public float getEyeHeight( @Nonnull EntityPose pose ) + { return 0; } @Override - public Vec3d getPos() { - return new Vec3d(this.getX(), this.getY(), this.getZ()); + public Vec3d getPos() + { + return new Vec3d( this.getX(), this.getY(), this.getZ() ); } @Override - public float getActiveEyeHeight(@Nonnull EntityPose pose, @Nonnull EntityDimensions size) { + public float getActiveEyeHeight( @Nonnull EntityPose pose, @Nonnull EntityDimensions size ) + { return 0; } @Override - public void enterCombat() { + public void enterCombat() + { } @Override - public void endCombat() { + public void endCombat() + { } @Override - public boolean startRiding(@Nonnull Entity entityIn, boolean force) { + public boolean startRiding( @Nonnull Entity entityIn, boolean force ) + { return false; } @Override - public void stopRiding() { + public void stopRiding() + { } @Override - public void openEditSignScreen(@Nonnull SignBlockEntity signTile) { + public void openEditSignScreen( @Nonnull SignBlockEntity signTile ) + { } //region Code which depends on the connection @Nonnull @Override - public OptionalInt openHandledScreen(@Nullable NamedScreenHandlerFactory prover) { + public OptionalInt openHandledScreen( @Nullable NamedScreenHandlerFactory prover ) + { return OptionalInt.empty(); } @Override - public void openHorseInventory(@Nonnull HorseBaseEntity horse, @Nonnull Inventory inventory) { + public void openHorseInventory( @Nonnull HorseBaseEntity horse, @Nonnull Inventory inventory ) + { } @Override - public void openEditBookScreen(@Nonnull ItemStack stack, @Nonnull Hand hand) { + public void openEditBookScreen( @Nonnull ItemStack stack, @Nonnull Hand hand ) + { } @Override - public void closeHandledScreen() { + public void closeHandledScreen() + { } @Override - public void updateCursorStack() { + public void updateCursorStack() + { } @Override - protected void onStatusEffectApplied(@Nonnull StatusEffectInstance id) { + protected void onStatusEffectApplied( @Nonnull StatusEffectInstance id ) + { } @Override - protected void onStatusEffectUpgraded(@Nonnull StatusEffectInstance id, boolean apply) { + protected void onStatusEffectUpgraded( @Nonnull StatusEffectInstance id, boolean apply ) + { } @Override - protected void onStatusEffectRemoved(@Nonnull StatusEffectInstance effect) { + protected void onStatusEffectRemoved( @Nonnull StatusEffectInstance effect ) + { } //endregion } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java index 6f59cdb3d..37d998c3c 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java @@ -6,46 +6,52 @@ package dan200.computercraft.shared.turtle.core; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; - import net.minecraft.item.ItemStack; -public class TurtleRefuelCommand implements ITurtleCommand { +import javax.annotation.Nonnull; + +public class TurtleRefuelCommand implements ITurtleCommand +{ private final int limit; - public TurtleRefuelCommand(int limit) { + public TurtleRefuelCommand( int limit ) + { this.limit = limit; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { int slot = turtle.getSelectedSlot(); ItemStack stack = turtle.getInventory() - .getStack(slot); - if (stack.isEmpty()) { - return TurtleCommandResult.failure("No items to combust"); + .getStack( slot ); + if( stack.isEmpty() ) + { + return TurtleCommandResult.failure( "No items to combust" ); } - TurtleRefuelEvent event = new TurtleRefuelEvent(turtle, stack); - if (TurtleEvent.post(event)) { - return TurtleCommandResult.failure(event.getFailureMessage()); + TurtleRefuelEvent event = new TurtleRefuelEvent( turtle, stack ); + if( TurtleEvent.post( event ) ) + { + return TurtleCommandResult.failure( event.getFailureMessage() ); } - if (event.getHandler() == null) { - return TurtleCommandResult.failure("Items not combustible"); + if( event.getHandler() == null ) + { + return TurtleCommandResult.failure( "Items not combustible" ); } - if (this.limit != 0) { - turtle.addFuel(event.getHandler() - .refuel(turtle, stack, slot, this.limit)); - turtle.playAnimation(TurtleAnimation.WAIT); + if( this.limit != 0 ) + { + turtle.addFuel( event.getHandler() + .refuel( turtle, stack, slot, this.limit ) ); + turtle.playAnimation( TurtleAnimation.WAIT ); } return TurtleCommandResult.success(); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java index 8c01e5b4e..bae644c73 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java @@ -6,10 +6,6 @@ package dan200.computercraft.shared.turtle.core; -import java.util.List; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; @@ -18,7 +14,6 @@ import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.api.turtle.event.TurtleInventoryEvent; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.ItemStorage; - import net.minecraft.entity.ItemEntity; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; @@ -28,114 +23,143 @@ import net.minecraft.util.math.Box; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class TurtleSuckCommand implements ITurtleCommand { +import javax.annotation.Nonnull; +import java.util.List; + +public class TurtleSuckCommand implements ITurtleCommand +{ private final InteractDirection m_direction; private final int m_quantity; - public TurtleSuckCommand(InteractDirection direction, int quantity) { + public TurtleSuckCommand( InteractDirection direction, int quantity ) + { this.m_direction = direction; this.m_quantity = quantity; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Sucking nothing is easy - if (this.m_quantity == 0) { - turtle.playAnimation(TurtleAnimation.WAIT); + if( this.m_quantity == 0 ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); } // Get world direction from direction - Direction direction = this.m_direction.toWorldDir(turtle); + Direction direction = this.m_direction.toWorldDir( turtle ); // Get inventory for thing in front World world = turtle.getWorld(); BlockPos turtlePosition = turtle.getPosition(); - BlockPos blockPosition = turtlePosition.offset(direction); + BlockPos blockPosition = turtlePosition.offset( direction ); Direction side = direction.getOpposite(); - Inventory inventory = InventoryUtil.getInventory(world, blockPosition, side); + Inventory inventory = InventoryUtil.getInventory( world, blockPosition, side ); // Fire the event, exiting if it is cancelled. - TurtlePlayer player = TurtlePlaceCommand.createPlayer(turtle, turtlePosition, direction); - TurtleInventoryEvent.Suck event = new TurtleInventoryEvent.Suck(turtle, player, world, blockPosition, inventory); - if (TurtleEvent.post(event)) { - return TurtleCommandResult.failure(event.getFailureMessage()); + TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, turtlePosition, direction ); + TurtleInventoryEvent.Suck event = new TurtleInventoryEvent.Suck( turtle, player, world, blockPosition, inventory ); + if( TurtleEvent.post( event ) ) + { + return TurtleCommandResult.failure( event.getFailureMessage() ); } - if (inventory != null) { + if( inventory != null ) + { // Take from inventory of thing in front - ItemStack stack = InventoryUtil.takeItems(this.m_quantity, ItemStorage.wrap(inventory)); - if (stack.isEmpty()) { - return TurtleCommandResult.failure("No items to take"); + ItemStack stack = InventoryUtil.takeItems( this.m_quantity, ItemStorage.wrap( inventory ) ); + if( stack.isEmpty() ) + { + return TurtleCommandResult.failure( "No items to take" ); } // Try to place into the turtle - ItemStack remainder = InventoryUtil.storeItems(stack, turtle.getItemHandler(), turtle.getSelectedSlot()); - if (!remainder.isEmpty()) { + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); + if( !remainder.isEmpty() ) + { // Put the remainder back in the inventory - InventoryUtil.storeItems(remainder, ItemStorage.wrap(inventory)); + InventoryUtil.storeItems( remainder, ItemStorage.wrap( inventory ) ); } // Return true if we consumed anything - if (remainder != stack) { - turtle.playAnimation(TurtleAnimation.WAIT); + if( remainder != stack ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); - } else { - return TurtleCommandResult.failure("No space for items"); } - } else { + else + { + return TurtleCommandResult.failure( "No space for items" ); + } + } + else + { // Suck up loose items off the ground - Box aabb = new Box(blockPosition.getX(), - blockPosition.getY(), - blockPosition.getZ(), - blockPosition.getX() + 1.0, - blockPosition.getY() + 1.0, - blockPosition.getZ() + 1.0); - List list = world.getEntitiesByClass(ItemEntity.class, aabb, EntityPredicates.VALID_ENTITY); - if (list.isEmpty()) { - return TurtleCommandResult.failure("No items to take"); + Box aabb = new Box( blockPosition.getX(), + blockPosition.getY(), + blockPosition.getZ(), + blockPosition.getX() + 1.0, + blockPosition.getY() + 1.0, + blockPosition.getZ() + 1.0 ); + List list = world.getEntitiesByClass( ItemEntity.class, aabb, EntityPredicates.VALID_ENTITY ); + if( list.isEmpty() ) + { + return TurtleCommandResult.failure( "No items to take" ); } - for (ItemEntity entity : list) { + for( ItemEntity entity : list ) + { // Suck up the item ItemStack stack = entity.getStack() - .copy(); + .copy(); ItemStack storeStack; ItemStack leaveStack; - if (stack.getCount() > this.m_quantity) { - storeStack = stack.split(this.m_quantity); + if( stack.getCount() > this.m_quantity ) + { + storeStack = stack.split( this.m_quantity ); leaveStack = stack; - } else { + } + else + { storeStack = stack; leaveStack = ItemStack.EMPTY; } - ItemStack remainder = InventoryUtil.storeItems(storeStack, turtle.getItemHandler(), turtle.getSelectedSlot()); + ItemStack remainder = InventoryUtil.storeItems( storeStack, turtle.getItemHandler(), turtle.getSelectedSlot() ); - if (remainder != storeStack) { - if (remainder.isEmpty() && leaveStack.isEmpty()) { + if( remainder != storeStack ) + { + if( remainder.isEmpty() && leaveStack.isEmpty() ) + { entity.remove(); - } else if (remainder.isEmpty()) { - entity.setStack(leaveStack); - } else if (leaveStack.isEmpty()) { - entity.setStack(remainder); - } else { - leaveStack.increment(remainder.getCount()); - entity.setStack(leaveStack); + } + else if( remainder.isEmpty() ) + { + entity.setStack( leaveStack ); + } + else if( leaveStack.isEmpty() ) + { + entity.setStack( remainder ); + } + else + { + leaveStack.increment( remainder.getCount() ); + entity.setStack( leaveStack ); } // Play fx - world.syncGlobalEvent(1000, turtlePosition, 0); // BLOCK_DISPENSER_DISPENSE - turtle.playAnimation(TurtleAnimation.WAIT); + world.syncGlobalEvent( 1000, turtlePosition, 0 ); // BLOCK_DISPENSER_DISPENSE + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); } } - return TurtleCommandResult.failure("No space for items"); + return TurtleCommandResult.failure( "No space for items" ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java index 1c33d1b86..e875f7e8b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java @@ -6,72 +6,77 @@ package dan200.computercraft.shared.turtle.core; -import java.util.Locale; +import dan200.computercraft.api.turtle.*; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Locale; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.TurtleVerb; - -public class TurtleToolCommand implements ITurtleCommand { +public class TurtleToolCommand implements ITurtleCommand +{ private final TurtleVerb verb; private final InteractDirection direction; private final TurtleSide side; - public TurtleToolCommand(TurtleVerb verb, InteractDirection direction, TurtleSide side) { + public TurtleToolCommand( TurtleVerb verb, InteractDirection direction, TurtleSide side ) + { this.verb = verb; this.direction = direction; this.side = side; } - public static TurtleToolCommand attack(InteractDirection direction, @Nullable TurtleSide side) { - return new TurtleToolCommand(TurtleVerb.ATTACK, direction, side); + public static TurtleToolCommand attack( InteractDirection direction, @Nullable TurtleSide side ) + { + return new TurtleToolCommand( TurtleVerb.ATTACK, direction, side ); } - public static TurtleToolCommand dig(InteractDirection direction, @Nullable TurtleSide side) { - return new TurtleToolCommand(TurtleVerb.DIG, direction, side); + public static TurtleToolCommand dig( InteractDirection direction, @Nullable TurtleSide side ) + { + return new TurtleToolCommand( TurtleVerb.DIG, direction, side ); } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { TurtleCommandResult firstFailure = null; - for (TurtleSide side : TurtleSide.values()) { - if (this.side != null && this.side != side) { + for( TurtleSide side : TurtleSide.values() ) + { + if( this.side != null && this.side != side ) + { continue; } - ITurtleUpgrade upgrade = turtle.getUpgrade(side); - if (upgrade == null || !upgrade.getType() - .isTool()) { + ITurtleUpgrade upgrade = turtle.getUpgrade( side ); + if( upgrade == null || !upgrade.getType() + .isTool() ) + { continue; } - TurtleCommandResult result = upgrade.useTool(turtle, side, this.verb, this.direction.toWorldDir(turtle)); - if (result.isSuccess()) { - switch (side) { - case LEFT: - turtle.playAnimation(TurtleAnimation.SWING_LEFT_TOOL); - break; - case RIGHT: - turtle.playAnimation(TurtleAnimation.SWING_RIGHT_TOOL); - break; - default: - turtle.playAnimation(TurtleAnimation.WAIT); - break; + TurtleCommandResult result = upgrade.useTool( turtle, side, this.verb, this.direction.toWorldDir( turtle ) ); + if( result.isSuccess() ) + { + switch( side ) + { + case LEFT: + turtle.playAnimation( TurtleAnimation.SWING_LEFT_TOOL ); + break; + case RIGHT: + turtle.playAnimation( TurtleAnimation.SWING_RIGHT_TOOL ); + break; + default: + turtle.playAnimation( TurtleAnimation.WAIT ); + break; } return result; - } else if (firstFailure == null) { + } + else if( firstFailure == null ) + { firstFailure = result; } } - return firstFailure != null ? firstFailure : TurtleCommandResult.failure("No tool to " + this.verb.name() - .toLowerCase(Locale.ROOT) + " with"); + return firstFailure != null ? firstFailure : TurtleCommandResult.failure( "No tool to " + this.verb.name() + .toLowerCase( Locale.ROOT ) + " with" ); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java index 47e04417a..adc971f09 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java @@ -6,48 +6,55 @@ package dan200.computercraft.shared.turtle.core; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.shared.util.InventoryUtil; - import net.minecraft.item.ItemStack; -public class TurtleTransferToCommand implements ITurtleCommand { +import javax.annotation.Nonnull; + +public class TurtleTransferToCommand implements ITurtleCommand +{ private final int m_slot; private final int m_quantity; - public TurtleTransferToCommand(int slot, int limit) { + public TurtleTransferToCommand( int slot, int limit ) + { this.m_slot = slot; this.m_quantity = limit; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { // Take stack - ItemStack stack = InventoryUtil.takeItems(this.m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot()); - if (stack.isEmpty()) { - turtle.playAnimation(TurtleAnimation.WAIT); + ItemStack stack = InventoryUtil.takeItems( this.m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + if( stack.isEmpty() ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); } // Store stack - ItemStack remainder = InventoryUtil.storeItems(stack, turtle.getItemHandler(), this.m_slot, 1, this.m_slot); - if (!remainder.isEmpty()) { + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), this.m_slot, 1, this.m_slot ); + if( !remainder.isEmpty() ) + { // Put the remainder back - InventoryUtil.storeItems(remainder, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot()); + InventoryUtil.storeItems( remainder, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); } // Return true if we moved anything - if (remainder != stack) { - turtle.playAnimation(TurtleAnimation.WAIT); + if( remainder != stack ) + { + turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); - } else { - return TurtleCommandResult.failure("No space for items"); + } + else + { + return TurtleCommandResult.failure( "No space for items" ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java index ab53aad7e..312f002cf 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java @@ -6,8 +6,6 @@ package dan200.computercraft.shared.turtle.core; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; @@ -16,37 +14,47 @@ import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.api.turtle.event.TurtleActionEvent; import dan200.computercraft.api.turtle.event.TurtleEvent; -public class TurtleTurnCommand implements ITurtleCommand { +import javax.annotation.Nonnull; + +public class TurtleTurnCommand implements ITurtleCommand +{ private final TurnDirection m_direction; - public TurtleTurnCommand(TurnDirection direction) { + public TurtleTurnCommand( TurnDirection direction ) + { this.m_direction = direction; } @Nonnull @Override - public TurtleCommandResult execute(@Nonnull ITurtleAccess turtle) { - TurtleActionEvent event = new TurtleActionEvent(turtle, TurtleAction.TURN); - if (TurtleEvent.post(event)) { - return TurtleCommandResult.failure(event.getFailureMessage()); + public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) + { + TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.TURN ); + if( TurtleEvent.post( event ) ) + { + return TurtleCommandResult.failure( event.getFailureMessage() ); } - switch (this.m_direction) { - case LEFT: { - turtle.setDirection(turtle.getDirection() - .rotateYCounterclockwise()); - turtle.playAnimation(TurtleAnimation.TURN_LEFT); - return TurtleCommandResult.success(); - } - case RIGHT: { - turtle.setDirection(turtle.getDirection() - .rotateYClockwise()); - turtle.playAnimation(TurtleAnimation.TURN_RIGHT); - return TurtleCommandResult.success(); - } - default: { - return TurtleCommandResult.failure("Unknown direction"); - } + switch( this.m_direction ) + { + case LEFT: + { + turtle.setDirection( turtle.getDirection() + .rotateYCounterclockwise() ); + turtle.playAnimation( TurtleAnimation.TURN_LEFT ); + return TurtleCommandResult.success(); + } + case RIGHT: + { + turtle.setDirection( turtle.getDirection() + .rotateYClockwise() ); + turtle.playAnimation( TurtleAnimation.TURN_RIGHT ); + return TurtleCommandResult.success(); + } + default: + { + return TurtleCommandResult.failure( "Unknown direction" ); + } } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java index 905e72022..487d11434 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java @@ -6,10 +6,6 @@ package dan200.computercraft.shared.turtle.inventory; -import java.util.function.Predicate; - -import javax.annotation.Nonnull; - import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.IComputer; @@ -18,7 +14,6 @@ import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.util.SingleIntArray; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -29,100 +24,127 @@ import net.minecraft.screen.ArrayPropertyDelegate; import net.minecraft.screen.PropertyDelegate; import net.minecraft.screen.slot.Slot; -public class ContainerTurtle extends ContainerComputerBase { +import javax.annotation.Nonnull; +import java.util.function.Predicate; + +public class ContainerTurtle extends ContainerComputerBase +{ public static final int PLAYER_START_Y = 134; public static final int TURTLE_START_X = 175; private final PropertyDelegate properties; - public ContainerTurtle(int id, PlayerInventory player, TurtleBrain turtle) { - this(id, - p -> turtle.getOwner() - .canPlayerUse(p), - turtle.getOwner() - .createServerComputer(), - turtle.getFamily(), - player, - turtle.getInventory(), - (SingleIntArray) turtle::getSelectedSlot); + public ContainerTurtle( int id, PlayerInventory player, TurtleBrain turtle ) + { + this( id, + p -> turtle.getOwner() + .canPlayerUse( p ), + turtle.getOwner() + .createServerComputer(), + turtle.getFamily(), + player, + turtle.getInventory(), + (SingleIntArray) turtle::getSelectedSlot ); } - private ContainerTurtle(int id, Predicate canUse, IComputer computer, ComputerFamily family, PlayerInventory playerInventory, - Inventory inventory, PropertyDelegate properties) { - super(ComputerCraftRegistry.ModContainers.TURTLE, id, canUse, computer, family); + private ContainerTurtle( int id, Predicate canUse, IComputer computer, ComputerFamily family, PlayerInventory playerInventory, + Inventory inventory, PropertyDelegate properties ) + { + super( ComputerCraftRegistry.ModContainers.TURTLE, id, canUse, computer, family ); this.properties = properties; - this.addProperties(properties); + this.addProperties( properties ); // Turtle inventory - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - this.addSlot(new Slot(inventory, x + y * 4, TURTLE_START_X + 1 + x * 18, PLAYER_START_Y + 1 + y * 18)); + for( int y = 0; y < 4; y++ ) + { + for( int x = 0; x < 4; x++ ) + { + this.addSlot( new Slot( inventory, x + y * 4, TURTLE_START_X + 1 + x * 18, PLAYER_START_Y + 1 + y * 18 ) ); } } // Player inventory - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 9; x++) { - this.addSlot(new Slot(playerInventory, x + y * 9 + 9, 8 + x * 18, PLAYER_START_Y + 1 + y * 18)); + for( int y = 0; y < 3; y++ ) + { + for( int x = 0; x < 9; x++ ) + { + this.addSlot( new Slot( playerInventory, x + y * 9 + 9, 8 + x * 18, PLAYER_START_Y + 1 + y * 18 ) ); } } // Player hotbar - for (int x = 0; x < 9; x++) { - this.addSlot(new Slot(playerInventory, x, 8 + x * 18, PLAYER_START_Y + 3 * 18 + 5)); + for( int x = 0; x < 9; x++ ) + { + this.addSlot( new Slot( playerInventory, x, 8 + x * 18, PLAYER_START_Y + 3 * 18 + 5 ) ); } } - public ContainerTurtle(int id, PlayerInventory player, PacketByteBuf packetByteBuf) { - this(id, player, new ComputerContainerData(packetByteBuf)); + public ContainerTurtle( int id, PlayerInventory player, PacketByteBuf packetByteBuf ) + { + this( id, player, new ComputerContainerData( packetByteBuf ) ); } - public ContainerTurtle(int id, PlayerInventory player, ComputerContainerData data) { - this(id, - x -> true, - getComputer(player, data), - data.getFamily(), - player, - new SimpleInventory(TileTurtle.INVENTORY_SIZE), - new ArrayPropertyDelegate(1)); + public ContainerTurtle( int id, PlayerInventory player, ComputerContainerData data ) + { + this( id, + x -> true, + getComputer( player, data ), + data.getFamily(), + player, + new SimpleInventory( TileTurtle.INVENTORY_SIZE ), + new ArrayPropertyDelegate( 1 ) ); } - public int getSelectedSlot() { - return this.properties.get(0); + public int getSelectedSlot() + { + return this.properties.get( 0 ); } @Nonnull @Override - public ItemStack transferSlot(@Nonnull PlayerEntity player, int slotNum) { - if (slotNum >= 0 && slotNum < 16) { - return this.tryItemMerge(player, slotNum, 16, 52, true); - } else if (slotNum >= 16) { - return this.tryItemMerge(player, slotNum, 0, 16, false); + public ItemStack transferSlot( @Nonnull PlayerEntity player, int slotNum ) + { + if( slotNum >= 0 && slotNum < 16 ) + { + return this.tryItemMerge( player, slotNum, 16, 52, true ); + } + else if( slotNum >= 16 ) + { + return this.tryItemMerge( player, slotNum, 0, 16, false ); } return ItemStack.EMPTY; } @Nonnull - private ItemStack tryItemMerge(PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse) { - Slot slot = this.slots.get(slotNum); + private ItemStack tryItemMerge( PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse ) + { + Slot slot = this.slots.get( slotNum ); ItemStack originalStack = ItemStack.EMPTY; - if (slot != null && slot.hasStack()) { + if( slot != null && slot.hasStack() ) + { ItemStack clickedStack = slot.getStack(); originalStack = clickedStack.copy(); - if (!this.insertItem(clickedStack, firstSlot, lastSlot, reverse)) { + if( !this.insertItem( clickedStack, firstSlot, lastSlot, reverse ) ) + { return ItemStack.EMPTY; } - if (clickedStack.isEmpty()) { - slot.setStack(ItemStack.EMPTY); - } else { + if( clickedStack.isEmpty() ) + { + slot.setStack( ItemStack.EMPTY ); + } + else + { slot.markDirty(); } - if (clickedStack.getCount() != originalStack.getCount()) { - slot.onTakeItem(player, clickedStack); - } else { + if( clickedStack.getCount() != originalStack.getCount() ) + { + slot.onTakeItem( player, clickedStack ); + } + else + { return ItemStack.EMPTY; } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java b/src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java index 6aeb23583..349fc3cab 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java @@ -6,23 +6,23 @@ package dan200.computercraft.shared.turtle.items; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.computer.items.IComputerItem; - import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; -public interface ITurtleItem extends IComputerItem, IColouredItem { - @Nullable - ITurtleUpgrade getUpgrade(@Nonnull ItemStack stack, @Nonnull TurtleSide side); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; - int getFuelLevel(@Nonnull ItemStack stack); +public interface ITurtleItem extends IComputerItem, IColouredItem +{ + @Nullable + ITurtleUpgrade getUpgrade( @Nonnull ItemStack stack, @Nonnull TurtleSide side ); + + int getFuelLevel( @Nonnull ItemStack stack ); @Nullable - Identifier getOverlay(@Nonnull ItemStack stack); + Identifier getOverlay( @Nonnull ItemStack stack ); } diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java index 9583f9b76..2e9046127 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java @@ -6,13 +6,6 @@ package dan200.computercraft.shared.turtle.items; -import static dan200.computercraft.shared.turtle.core.TurtleBrain.NBT_FUEL; -import static dan200.computercraft.shared.turtle.core.TurtleBrain.NBT_LEFT_UPGRADE; -import static dan200.computercraft.shared.turtle.core.TurtleBrain.NBT_OVERLAY; -import static dan200.computercraft.shared.turtle.core.TurtleBrain.NBT_RIGHT_UPGRADE; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.TurtleUpgrades; @@ -20,7 +13,6 @@ import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.items.ItemComputerBase; import dan200.computercraft.shared.turtle.blocks.BlockTurtle; - import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; @@ -30,58 +22,73 @@ import net.minecraft.text.TranslatableText; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; -public class ItemTurtle extends ItemComputerBase implements ITurtleItem { - public ItemTurtle(BlockTurtle block, Settings settings) { - super(block, settings); +import javax.annotation.Nonnull; + +import static dan200.computercraft.shared.turtle.core.TurtleBrain.*; + +public class ItemTurtle extends ItemComputerBase implements ITurtleItem +{ + public ItemTurtle( BlockTurtle block, Settings settings ) + { + super( block, settings ); } @Override - public void appendStacks(@Nonnull ItemGroup group, @Nonnull DefaultedList list) { - if (!this.isIn(group)) { + public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList list ) + { + if( !this.isIn( group ) ) + { return; } ComputerFamily family = this.getFamily(); - list.add(this.create(-1, null, -1, null, null, 0, null)); + list.add( this.create( -1, null, -1, null, null, 0, null ) ); TurtleUpgrades.getVanillaUpgrades() - .filter(x -> TurtleUpgrades.suitableForFamily(family, x)) - .map(x -> this.create(-1, null, -1, null, x, 0, null)) - .forEach(list::add); + .filter( x -> TurtleUpgrades.suitableForFamily( family, x ) ) + .map( x -> this.create( -1, null, -1, null, x, 0, null ) ) + .forEach( list::add ); } - public ItemStack create(int id, String label, int colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, int fuelLevel, Identifier overlay) { + public ItemStack create( int id, String label, int colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, int fuelLevel, Identifier overlay ) + { // Build the stack - ItemStack stack = new ItemStack(this); - if (label != null) { - stack.setCustomName(new LiteralText(label)); + ItemStack stack = new ItemStack( this ); + if( label != null ) + { + stack.setCustomName( new LiteralText( label ) ); } - if (id >= 0) { + if( id >= 0 ) + { stack.getOrCreateTag() - .putInt(NBT_ID, id); + .putInt( NBT_ID, id ); } - IColouredItem.setColourBasic(stack, colour); - if (fuelLevel > 0) { + IColouredItem.setColourBasic( stack, colour ); + if( fuelLevel > 0 ) + { stack.getOrCreateTag() - .putInt(NBT_FUEL, fuelLevel); + .putInt( NBT_FUEL, fuelLevel ); } - if (overlay != null) { + if( overlay != null ) + { stack.getOrCreateTag() - .putString(NBT_OVERLAY, overlay.toString()); + .putString( NBT_OVERLAY, overlay.toString() ); } - if (leftUpgrade != null) { + if( leftUpgrade != null ) + { stack.getOrCreateTag() - .putString(NBT_LEFT_UPGRADE, - leftUpgrade.getUpgradeID() - .toString()); + .putString( NBT_LEFT_UPGRADE, + leftUpgrade.getUpgradeID() + .toString() ); } - if (rightUpgrade != null) { + if( rightUpgrade != null ) + { stack.getOrCreateTag() - .putString(NBT_RIGHT_UPGRADE, - rightUpgrade.getUpgradeID() - .toString()); + .putString( NBT_RIGHT_UPGRADE, + rightUpgrade.getUpgradeID() + .toString() ); } return stack; @@ -89,20 +96,28 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem { @Nonnull @Override - public Text getName(@Nonnull ItemStack stack) { - String baseString = this.getTranslationKey(stack); - ITurtleUpgrade left = this.getUpgrade(stack, TurtleSide.LEFT); - ITurtleUpgrade right = this.getUpgrade(stack, TurtleSide.RIGHT); - if (left != null && right != null) { - return new TranslatableText(baseString + ".upgraded_twice", - new TranslatableText(right.getUnlocalisedAdjective()), - new TranslatableText(left.getUnlocalisedAdjective())); - } else if (left != null) { - return new TranslatableText(baseString + ".upgraded", new TranslatableText(left.getUnlocalisedAdjective())); - } else if (right != null) { - return new TranslatableText(baseString + ".upgraded", new TranslatableText(right.getUnlocalisedAdjective())); - } else { - return new TranslatableText(baseString); + public Text getName( @Nonnull ItemStack stack ) + { + String baseString = this.getTranslationKey( stack ); + ITurtleUpgrade left = this.getUpgrade( stack, TurtleSide.LEFT ); + ITurtleUpgrade right = this.getUpgrade( stack, TurtleSide.RIGHT ); + if( left != null && right != null ) + { + return new TranslatableText( baseString + ".upgraded_twice", + new TranslatableText( right.getUnlocalisedAdjective() ), + new TranslatableText( left.getUnlocalisedAdjective() ) ); + } + else if( left != null ) + { + return new TranslatableText( baseString + ".upgraded", new TranslatableText( left.getUnlocalisedAdjective() ) ); + } + else if( right != null ) + { + return new TranslatableText( baseString + ".upgraded", new TranslatableText( right.getUnlocalisedAdjective() ) ); + } + else + { + return new TranslatableText( baseString ); } } @@ -131,32 +146,37 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem { // } @Override - public ITurtleUpgrade getUpgrade(@Nonnull ItemStack stack, @Nonnull TurtleSide side) { + public ITurtleUpgrade getUpgrade( @Nonnull ItemStack stack, @Nonnull TurtleSide side ) + { CompoundTag tag = stack.getTag(); - if (tag == null) { + if( tag == null ) + { return null; } String key = side == TurtleSide.LEFT ? NBT_LEFT_UPGRADE : NBT_RIGHT_UPGRADE; - return tag.contains(key) ? TurtleUpgrades.get(tag.getString(key)) : null; + return tag.contains( key ) ? TurtleUpgrades.get( tag.getString( key ) ) : null; } @Override - public int getFuelLevel(@Nonnull ItemStack stack) { + public int getFuelLevel( @Nonnull ItemStack stack ) + { CompoundTag tag = stack.getTag(); - return tag != null && tag.contains(NBT_FUEL) ? tag.getInt(NBT_FUEL) : 0; + return tag != null && tag.contains( NBT_FUEL ) ? tag.getInt( NBT_FUEL ) : 0; } @Override - public Identifier getOverlay(@Nonnull ItemStack stack) { + public Identifier getOverlay( @Nonnull ItemStack stack ) + { CompoundTag tag = stack.getTag(); - return tag != null && tag.contains(NBT_OVERLAY) ? new Identifier(tag.getString(NBT_OVERLAY)) : null; + return tag != null && tag.contains( NBT_OVERLAY ) ? new Identifier( tag.getString( NBT_OVERLAY ) ) : null; } @Override - public ItemStack withFamily(@Nonnull ItemStack stack, @Nonnull ComputerFamily family) { - return TurtleItemFactory.create(this.getComputerID(stack), this.getLabel(stack), this.getColour(stack), - family, this.getUpgrade(stack, TurtleSide.LEFT), - this.getUpgrade(stack, TurtleSide.RIGHT), this.getFuelLevel(stack), this.getOverlay(stack)); + public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) + { + return TurtleItemFactory.create( this.getComputerID( stack ), this.getLabel( stack ), this.getColour( stack ), + family, this.getUpgrade( stack, TurtleSide.LEFT ), + this.getUpgrade( stack, TurtleSide.RIGHT ), this.getFuelLevel( stack ), this.getOverlay( stack ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java b/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java index c75a6f30b..9d604502f 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java +++ b/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java @@ -6,45 +6,48 @@ package dan200.computercraft.shared.turtle.items; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.turtle.blocks.ITurtleTile; - import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; -public final class TurtleItemFactory { +import javax.annotation.Nonnull; + +public final class TurtleItemFactory +{ private TurtleItemFactory() {} @Nonnull - public static ItemStack create(ITurtleTile turtle) { + public static ItemStack create( ITurtleTile turtle ) + { ITurtleAccess access = turtle.getAccess(); - return create(turtle.getComputerID(), - turtle.getLabel(), - turtle.getColour(), - turtle.getFamily(), - access.getUpgrade(TurtleSide.LEFT), - access.getUpgrade(TurtleSide.RIGHT), - access.getFuelLevel(), - turtle.getOverlay()); + return create( turtle.getComputerID(), + turtle.getLabel(), + turtle.getColour(), + turtle.getFamily(), + access.getUpgrade( TurtleSide.LEFT ), + access.getUpgrade( TurtleSide.RIGHT ), + access.getFuelLevel(), + turtle.getOverlay() ); } @Nonnull - public static ItemStack create(int id, String label, int colour, ComputerFamily family, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, - int fuelLevel, Identifier overlay) { - switch (family) { - case NORMAL: - return ComputerCraftRegistry.ModItems.TURTLE_NORMAL.create(id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay); - case ADVANCED: - return ComputerCraftRegistry.ModItems.TURTLE_ADVANCED.create(id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay); - default: - return ItemStack.EMPTY; + public static ItemStack create( int id, String label, int colour, ComputerFamily family, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, + int fuelLevel, Identifier overlay ) + { + switch( family ) + { + case NORMAL: + return ComputerCraftRegistry.ModItems.TURTLE_NORMAL.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + case ADVANCED: + return ComputerCraftRegistry.ModItems.TURTLE_ADVANCED.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + default: + return ItemStack.EMPTY; } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java index 61032889f..4df8575fb 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java @@ -6,46 +6,51 @@ package dan200.computercraft.shared.turtle.recipes; -import javax.annotation.Nonnull; - import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.items.IComputerItem; import dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe; import dan200.computercraft.shared.turtle.items.TurtleItemFactory; - import net.minecraft.item.ItemStack; import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.RecipeSerializer; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; -public final class TurtleRecipe extends ComputerFamilyRecipe { - public static final RecipeSerializer SERIALIZER = - new dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe.Serializer() { - @Override - protected TurtleRecipe create(Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result - , ComputerFamily family) { - return new TurtleRecipe(identifier, group, width, height, ingredients, result, family); - } - }; +import javax.annotation.Nonnull; - private TurtleRecipe(Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family) { - super(identifier, group, width, height, ingredients, result, family); +public final class TurtleRecipe extends ComputerFamilyRecipe +{ + public static final RecipeSerializer SERIALIZER = + new dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe.Serializer() + { + @Override + protected TurtleRecipe create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result + , ComputerFamily family ) + { + return new TurtleRecipe( identifier, group, width, height, ingredients, result, family ); + } + }; + + private TurtleRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, + ComputerFamily family ) + { + super( identifier, group, width, height, ingredients, result, family ); } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } @Nonnull @Override - protected ItemStack convert(@Nonnull IComputerItem item, @Nonnull ItemStack stack) { - int computerID = item.getComputerID(stack); - String label = item.getLabel(stack); + protected ItemStack convert( @Nonnull IComputerItem item, @Nonnull ItemStack stack ) + { + int computerID = item.getComputerID( stack ); + String label = item.getLabel( stack ); - return TurtleItemFactory.create(computerID, label, -1, this.getFamily(), null, null, 0, null); + return TurtleItemFactory.create( computerID, label, -1, this.getFamily(), null, null, 0, null ); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java index a3ef94120..da301a48a 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java @@ -6,15 +6,12 @@ package dan200.computercraft.shared.turtle.recipes; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.TurtleUpgrades; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.turtle.items.ITurtleItem; import dan200.computercraft.shared.turtle.items.TurtleItemFactory; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.RecipeSerializer; @@ -23,77 +20,108 @@ import net.minecraft.recipe.SpecialRecipeSerializer; import net.minecraft.util.Identifier; import net.minecraft.world.World; -public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe { - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>(TurtleUpgradeRecipe::new); +import javax.annotation.Nonnull; - private TurtleUpgradeRecipe(Identifier id) { - super(id); +public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe +{ + public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( TurtleUpgradeRecipe::new ); + + private TurtleUpgradeRecipe( Identifier id ) + { + super( id ); } @Nonnull @Override - public ItemStack getOutput() { - return TurtleItemFactory.create(-1, null, -1, ComputerFamily.NORMAL, null, null, 0, null); + public ItemStack getOutput() + { + return TurtleItemFactory.create( -1, null, -1, ComputerFamily.NORMAL, null, null, 0, null ); } @Override - public boolean matches(@Nonnull CraftingInventory inventory, @Nonnull World world) { - return !this.craft(inventory).isEmpty(); + public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) + { + return !this.craft( inventory ).isEmpty(); } @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inventory) { + public ItemStack craft( @Nonnull CraftingInventory inventory ) + { // Scan the grid for a row containing a turtle and 1 or 2 items ItemStack leftItem = ItemStack.EMPTY; ItemStack turtle = ItemStack.EMPTY; ItemStack rightItem = ItemStack.EMPTY; - for (int y = 0; y < inventory.getHeight(); y++) { - if (turtle.isEmpty()) { + for( int y = 0; y < inventory.getHeight(); y++ ) + { + if( turtle.isEmpty() ) + { // Search this row for potential turtles boolean finishedRow = false; - for (int x = 0; x < inventory.getWidth(); x++) { - ItemStack item = inventory.getStack(x + y * inventory.getWidth()); - if (!item.isEmpty()) { - if (finishedRow) { + for( int x = 0; x < inventory.getWidth(); x++ ) + { + ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); + if( !item.isEmpty() ) + { + if( finishedRow ) + { return ItemStack.EMPTY; } - if (item.getItem() instanceof ITurtleItem) { + if( item.getItem() instanceof ITurtleItem ) + { // Item is a turtle - if (turtle.isEmpty()) { + if( turtle.isEmpty() ) + { turtle = item; - } else { - return ItemStack.EMPTY; } - } else { - // Item is not a turtle - if (turtle.isEmpty() && leftItem.isEmpty()) { - leftItem = item; - } else if (!turtle.isEmpty() && rightItem.isEmpty()) { - rightItem = item; - } else { + else + { return ItemStack.EMPTY; } } - } else { + else + { + // Item is not a turtle + if( turtle.isEmpty() && leftItem.isEmpty() ) + { + leftItem = item; + } + else if( !turtle.isEmpty() && rightItem.isEmpty() ) + { + rightItem = item; + } + else + { + return ItemStack.EMPTY; + } + } + } + else + { // Item is empty - if (!leftItem.isEmpty() || !turtle.isEmpty()) { + if( !leftItem.isEmpty() || !turtle.isEmpty() ) + { finishedRow = true; } } } // If we found anything, check we found a turtle too - if (turtle.isEmpty() && (!leftItem.isEmpty() || !rightItem.isEmpty())) { + if( turtle.isEmpty() && (!leftItem.isEmpty() || !rightItem.isEmpty()) ) + { return ItemStack.EMPTY; } - } else { + } + else + { // Turtle is already found, just check this row is empty - for (int x = 0; x < inventory.getWidth(); x++) { - ItemStack item = inventory.getStack(x + y * inventory.getWidth()); - if (!item.isEmpty()) { + for( int x = 0; x < inventory.getWidth(); x++ ) + { + ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); + if( !item.isEmpty() ) + { return ItemStack.EMPTY; } } @@ -101,7 +129,8 @@ public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe { } // See if we found a turtle + one or more items - if (turtle.isEmpty() || leftItem.isEmpty() && rightItem.isEmpty()) { + if( turtle.isEmpty() || leftItem.isEmpty() && rightItem.isEmpty() ) + { return ItemStack.EMPTY; } @@ -110,25 +139,30 @@ public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe { ITurtleItem itemTurtle = (ITurtleItem) turtle.getItem(); ComputerFamily family = itemTurtle.getFamily(); ITurtleUpgrade[] upgrades = new ITurtleUpgrade[] { - itemTurtle.getUpgrade(turtle, TurtleSide.LEFT), - itemTurtle.getUpgrade(turtle, TurtleSide.RIGHT), - }; + itemTurtle.getUpgrade( turtle, TurtleSide.LEFT ), + itemTurtle.getUpgrade( turtle, TurtleSide.RIGHT ), + }; // Get the upgrades for the new items ItemStack[] items = new ItemStack[] { rightItem, leftItem }; - for (int i = 0; i < 2; i++) { - if (!items[i].isEmpty()) { - ITurtleUpgrade itemUpgrade = TurtleUpgrades.get(items[i]); - if (itemUpgrade == null) { + for( int i = 0; i < 2; i++ ) + { + if( !items[i].isEmpty() ) + { + ITurtleUpgrade itemUpgrade = TurtleUpgrades.get( items[i] ); + if( itemUpgrade == null ) + { return ItemStack.EMPTY; } - if (upgrades[i] != null) { + if( upgrades[i] != null ) + { return ItemStack.EMPTY; } - if (!TurtleUpgrades.suitableForFamily(family, itemUpgrade)) { + if( !TurtleUpgrades.suitableForFamily( family, itemUpgrade ) ) + { return ItemStack.EMPTY; } upgrades[i] = itemUpgrade; @@ -136,22 +170,24 @@ public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe { } // Construct the new stack - int computerID = itemTurtle.getComputerID(turtle); - String label = itemTurtle.getLabel(turtle); - int fuelLevel = itemTurtle.getFuelLevel(turtle); - int colour = itemTurtle.getColour(turtle); - Identifier overlay = itemTurtle.getOverlay(turtle); - return TurtleItemFactory.create(computerID, label, colour, family, upgrades[0], upgrades[1], fuelLevel, overlay); + int computerID = itemTurtle.getComputerID( turtle ); + String label = itemTurtle.getLabel( turtle ); + int fuelLevel = itemTurtle.getFuelLevel( turtle ); + int colour = itemTurtle.getColour( turtle ); + Identifier overlay = itemTurtle.getOverlay( turtle ); + return TurtleItemFactory.create( computerID, label, colour, family, upgrades[0], upgrades[1], fuelLevel, overlay ); } @Override - public boolean fits(int x, int y) { + public boolean fits( int x, int y ) + { return x >= 3 && y >= 1; } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java index bffffadfe..959ed2b7b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java @@ -6,10 +6,6 @@ package dan200.computercraft.shared.turtle.upgrades; -import java.util.Optional; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; @@ -17,6 +13,9 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.shared.turtle.core.TurtleCraftCommand; +import javax.annotation.Nonnull; +import java.util.Optional; + /** * The workbench peripheral allows you to craft items within the turtle's inventory. * @@ -24,36 +23,43 @@ import dan200.computercraft.shared.turtle.core.TurtleCraftCommand; * @hidden * @cc.see turtle.craft This uses the {@link CraftingTablePeripheral} peripheral to craft items. */ -public class CraftingTablePeripheral implements IPeripheral { +public class CraftingTablePeripheral implements IPeripheral +{ private final ITurtleAccess turtle; - public CraftingTablePeripheral(ITurtleAccess turtle) { + public CraftingTablePeripheral( ITurtleAccess turtle ) + { this.turtle = turtle; } @Nonnull @Override - public String getType() { + public String getType() + { return "workbench"; } @Nonnull @Override - public Object getTarget() { + public Object getTarget() + { return this.turtle; } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return other instanceof CraftingTablePeripheral; } @LuaFunction - public final MethodResult craft(Optional count) throws LuaException { - int limit = count.orElse(64); - if (limit < 0 || limit > 64) { - throw new LuaException("Crafting count " + limit + " out of range"); + public final MethodResult craft( Optional count ) throws LuaException + { + int limit = count.orElse( 64 ); + if( limit < 0 || limit > 64 ) + { + throw new LuaException( "Crafting count " + limit + " out of range" ); } - return this.turtle.executeCommand(new TurtleCraftCommand(limit)); + return this.turtle.executeCommand( new TurtleCraftCommand( limit ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java index 1b1563f1b..635536c0f 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java @@ -10,21 +10,26 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; -public class TurtleAxe extends TurtleTool { - public TurtleAxe(Identifier id, String adjective, Item item) { - super(id, adjective, item); +public class TurtleAxe extends TurtleTool +{ + public TurtleAxe( Identifier id, String adjective, Item item ) + { + super( id, adjective, item ); } - public TurtleAxe(Identifier id, Item item) { - super(id, item); + public TurtleAxe( Identifier id, Item item ) + { + super( id, item ); } - public TurtleAxe(Identifier id, ItemStack craftItem, ItemStack toolItem) { - super(id, craftItem, toolItem); + public TurtleAxe( Identifier id, ItemStack craftItem, ItemStack toolItem ) + { + super( id, craftItem, toolItem ); } @Override - protected float getDamageMultiplier() { + protected float getDamageMultiplier() + { return 6.0f; } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java index 81c3540e7..0ebfc06a3 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java @@ -6,49 +6,55 @@ package dan200.computercraft.shared.turtle.upgrades; -import javax.annotation.Nonnull; - import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleUpgradeType; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.Blocks; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.util.Identifier; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; -public class TurtleCraftingTable extends AbstractTurtleUpgrade { - @Environment (EnvType.CLIENT) private ModelIdentifier m_leftModel; +public class TurtleCraftingTable extends AbstractTurtleUpgrade +{ + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_leftModel; - @Environment (EnvType.CLIENT) private ModelIdentifier m_rightModel; + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_rightModel; - public TurtleCraftingTable(Identifier id) { - super(id, TurtleUpgradeType.PERIPHERAL, Blocks.CRAFTING_TABLE); + public TurtleCraftingTable( Identifier id ) + { + super( id, TurtleUpgradeType.PERIPHERAL, Blocks.CRAFTING_TABLE ); } @Override - public IPeripheral createPeripheral(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side) { - return new CraftingTablePeripheral(turtle); + public IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) + { + return new CraftingTablePeripheral( turtle ); } @Nonnull @Override - @Environment (EnvType.CLIENT) - public TransformedModel getModel(ITurtleAccess turtle, @Nonnull TurtleSide side) { + @Environment( EnvType.CLIENT ) + public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) + { this.loadModelLocations(); - return TransformedModel.of(side == TurtleSide.LEFT ? this.m_leftModel : this.m_rightModel); + return TransformedModel.of( side == TurtleSide.LEFT ? this.m_leftModel : this.m_rightModel ); } - @Environment (EnvType.CLIENT) - private void loadModelLocations() { - if (this.m_leftModel == null) { - this.m_leftModel = new ModelIdentifier("computercraft:turtle_crafting_table_left", "inventory"); - this.m_rightModel = new ModelIdentifier("computercraft:turtle_crafting_table_right", "inventory"); + @Environment( EnvType.CLIENT ) + private void loadModelLocations() + { + if( this.m_leftModel == null ) + { + this.m_leftModel = new ModelIdentifier( "computercraft:turtle_crafting_table_left", "inventory" ); + this.m_rightModel = new ModelIdentifier( "computercraft:turtle_crafting_table_right", "inventory" ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java index 2893203d8..97d92eaa5 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java @@ -6,15 +6,12 @@ package dan200.computercraft.shared.turtle.upgrades; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleVerb; import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; import dan200.computercraft.shared.turtle.core.TurtlePlayer; - import net.minecraft.block.BlockState; import net.minecraft.block.Material; import net.minecraft.item.Item; @@ -24,35 +21,46 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class TurtleHoe extends TurtleTool { - public TurtleHoe(Identifier id, String adjective, Item item) { - super(id, adjective, item); +import javax.annotation.Nonnull; + +public class TurtleHoe extends TurtleTool +{ + public TurtleHoe( Identifier id, String adjective, Item item ) + { + super( id, adjective, item ); } - public TurtleHoe(Identifier id, Item item) { - super(id, item); + public TurtleHoe( Identifier id, Item item ) + { + super( id, item ); } - public TurtleHoe(Identifier id, ItemStack craftItem, ItemStack toolItem) { - super(id, craftItem, toolItem); + public TurtleHoe( Identifier id, ItemStack craftItem, ItemStack toolItem ) + { + super( id, craftItem, toolItem ); } @Nonnull @Override - public TurtleCommandResult useTool(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction) { - if (verb == TurtleVerb.DIG) { + public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) + { + if( verb == TurtleVerb.DIG ) + { ItemStack hoe = this.item.copy(); - ItemStack remainder = TurtlePlaceCommand.deploy(hoe, turtle, direction, null, null); - if (remainder != hoe) { + ItemStack remainder = TurtlePlaceCommand.deploy( hoe, turtle, direction, null, null ); + if( remainder != hoe ) + { return TurtleCommandResult.success(); } } - return super.useTool(turtle, side, verb, direction); + return super.useTool( turtle, side, verb, direction ); } @Override - protected boolean canBreakBlock(BlockState state, World world, BlockPos pos, TurtlePlayer player) { - if (!super.canBreakBlock(state, world, pos, player)) { + protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) + { + if( !super.canBreakBlock( state, world, pos, player ) ) + { return false; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java index c7fabe344..3aa249829 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java @@ -6,17 +6,9 @@ package dan200.computercraft.shared.turtle.upgrades; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.core.TurtlePlayer; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; @@ -26,33 +18,46 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -public class TurtleInventoryCrafting extends CraftingInventory { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TurtleInventoryCrafting extends CraftingInventory +{ private ITurtleAccess m_turtle; private int m_xStart; private int m_yStart; - @SuppressWarnings ("ConstantConditions") - public TurtleInventoryCrafting(ITurtleAccess turtle) { + @SuppressWarnings( "ConstantConditions" ) + public TurtleInventoryCrafting( ITurtleAccess turtle ) + { // Passing null in here is evil, but we don't have a container present. We override most methods in order to // avoid throwing any NPEs. - super(null, 0, 0); + super( null, 0, 0 ); this.m_turtle = turtle; this.m_xStart = 0; this.m_yStart = 0; } @Nullable - private Recipe tryCrafting(int xStart, int yStart) { + private Recipe tryCrafting( int xStart, int yStart ) + { this.m_xStart = xStart; this.m_yStart = yStart; // Check the non-relevant parts of the inventory are empty - for (int x = 0; x < TileTurtle.INVENTORY_WIDTH; x++) { - for (int y = 0; y < TileTurtle.INVENTORY_HEIGHT; y++) { - if (x < this.m_xStart || x >= this.m_xStart + 3 || y < this.m_yStart || y >= this.m_yStart + 3) { - if (!this.m_turtle.getInventory() - .getStack(x + y * TileTurtle.INVENTORY_WIDTH) - .isEmpty()) { + for( int x = 0; x < TileTurtle.INVENTORY_WIDTH; x++ ) + { + for( int y = 0; y < TileTurtle.INVENTORY_HEIGHT; y++ ) + { + if( x < this.m_xStart || x >= this.m_xStart + 3 || y < this.m_yStart || y >= this.m_yStart + 3 ) + { + if( !this.m_turtle.getInventory() + .getStack( x + y * TileTurtle.INVENTORY_WIDTH ) + .isEmpty() ) + { return null; } } @@ -61,72 +66,89 @@ public class TurtleInventoryCrafting extends CraftingInventory { // Check the actual crafting return this.m_turtle.getWorld() - .getRecipeManager() - .getFirstMatch(RecipeType.CRAFTING, this, this.m_turtle.getWorld()) - .orElse(null); + .getRecipeManager() + .getFirstMatch( RecipeType.CRAFTING, this, this.m_turtle.getWorld() ) + .orElse( null ); } @Nullable - public List doCrafting(World world, int maxCount) { - if (world.isClient || !(world instanceof ServerWorld)) { + public List doCrafting( World world, int maxCount ) + { + if( world.isClient || !(world instanceof ServerWorld) ) + { return null; } // Find out what we can craft - Recipe recipe = this.tryCrafting(0, 0); - if (recipe == null) { - recipe = this.tryCrafting(0, 1); + Recipe recipe = this.tryCrafting( 0, 0 ); + if( recipe == null ) + { + recipe = this.tryCrafting( 0, 1 ); } - if (recipe == null) { - recipe = this.tryCrafting(1, 0); + if( recipe == null ) + { + recipe = this.tryCrafting( 1, 0 ); } - if (recipe == null) { - recipe = this.tryCrafting(1, 1); + if( recipe == null ) + { + recipe = this.tryCrafting( 1, 1 ); } - if (recipe == null) { + if( recipe == null ) + { return null; } // Special case: craft(0) just returns an empty list if crafting was possible - if (maxCount == 0) { + if( maxCount == 0 ) + { return Collections.emptyList(); } - TurtlePlayer player = TurtlePlayer.get(this.m_turtle); + TurtlePlayer player = TurtlePlayer.get( this.m_turtle ); ArrayList results = new ArrayList<>(); - for (int i = 0; i < maxCount && recipe.matches(this, world); i++) { - ItemStack result = recipe.craft(this); - if (result.isEmpty()) { + for( int i = 0; i < maxCount && recipe.matches( this, world ); i++ ) + { + ItemStack result = recipe.craft( this ); + if( result.isEmpty() ) + { break; } - results.add(result); + results.add( result ); - result.onCraft(world, player, result.getCount()); - DefaultedList remainders = recipe.getRemainingStacks(this); + result.onCraft( world, player, result.getCount() ); + DefaultedList remainders = recipe.getRemainingStacks( this ); - for (int slot = 0; slot < remainders.size(); slot++) { - ItemStack existing = this.getStack(slot); - ItemStack remainder = remainders.get(slot); + for( int slot = 0; slot < remainders.size(); slot++ ) + { + ItemStack existing = this.getStack( slot ); + ItemStack remainder = remainders.get( slot ); - if (!existing.isEmpty()) { - this.removeStack(slot, 1); - existing = this.getStack(slot); + if( !existing.isEmpty() ) + { + this.removeStack( slot, 1 ); + existing = this.getStack( slot ); } - if (remainder.isEmpty()) { + if( remainder.isEmpty() ) + { continue; } // Either update the current stack or add it to the remainder list (to be inserted into the inventory // afterwards). - if (existing.isEmpty()) { - this.setStack(slot, remainder); - } else if (ItemStack.areItemsEqualIgnoreDamage(existing, remainder) && ItemStack.areTagsEqual(existing, remainder)) { - remainder.increment(existing.getCount()); - this.setStack(slot, remainder); - } else { - results.add(remainder); + if( existing.isEmpty() ) + { + this.setStack( slot, remainder ); + } + else if( ItemStack.areItemsEqualIgnoreDamage( existing, remainder ) && ItemStack.areTagsEqual( existing, remainder ) ) + { + remainder.increment( existing.getCount() ); + this.setStack( slot, remainder ); + } + else + { + results.add( remainder ); } } } @@ -135,25 +157,34 @@ public class TurtleInventoryCrafting extends CraftingInventory { } @Override - public int getMaxCountPerStack() { + public int getMaxCountPerStack() + { return this.m_turtle.getInventory() - .getMaxCountPerStack(); - } @Override - public int getWidth() { + .getMaxCountPerStack(); + } + + @Override + public int getWidth() + { return 3; } @Override - public boolean isValid(int i, @Nonnull ItemStack stack) { - i = this.modifyIndex(i); + public boolean isValid( int i, @Nonnull ItemStack stack ) + { + i = this.modifyIndex( i ); return this.m_turtle.getInventory() - .isValid(i, stack); - } @Override - public int getHeight() { + .isValid( i, stack ); + } + + @Override + public int getHeight() + { return 3; } - private int modifyIndex(int index) { + private int modifyIndex( int index ) + { int x = this.m_xStart + index % this.getWidth(); int y = this.m_yStart + index / this.getHeight(); return x >= 0 && x < TileTurtle.INVENTORY_WIDTH && y >= 0 && y < TileTurtle.INVENTORY_HEIGHT ? x + y * TileTurtle.INVENTORY_WIDTH : -1; @@ -162,62 +193,69 @@ public class TurtleInventoryCrafting extends CraftingInventory { // IInventory implementation @Override - public int size() { + public int size() + { return this.getWidth() * this.getHeight(); } @Nonnull @Override - public ItemStack getStack(int i) { - i = this.modifyIndex(i); + public ItemStack getStack( int i ) + { + i = this.modifyIndex( i ); return this.m_turtle.getInventory() - .getStack(i); + .getStack( i ); } @Nonnull @Override - public ItemStack removeStack(int i) { - i = this.modifyIndex(i); + public ItemStack removeStack( int i ) + { + i = this.modifyIndex( i ); return this.m_turtle.getInventory() - .removeStack(i); + .removeStack( i ); } @Nonnull @Override - public ItemStack removeStack(int i, int size) { - i = this.modifyIndex(i); + public ItemStack removeStack( int i, int size ) + { + i = this.modifyIndex( i ); return this.m_turtle.getInventory() - .removeStack(i, size); + .removeStack( i, size ); } @Override - public void setStack(int i, @Nonnull ItemStack stack) { - i = this.modifyIndex(i); + public void setStack( int i, @Nonnull ItemStack stack ) + { + i = this.modifyIndex( i ); this.m_turtle.getInventory() - .setStack(i, stack); + .setStack( i, stack ); } - @Override - public void markDirty() { + public void markDirty() + { this.m_turtle.getInventory() - .markDirty(); + .markDirty(); } @Override - public boolean canPlayerUse(@Nonnull PlayerEntity player) { + public boolean canPlayerUse( @Nonnull PlayerEntity player ) + { return true; } - @Override - public void clear() { - for (int i = 0; i < this.size(); i++) { - int j = this.modifyIndex(i); + public void clear() + { + for( int i = 0; i < this.size(); i++ ) + { + int j = this.modifyIndex( i ); this.m_turtle.getInventory() - .setStack(j, ItemStack.EMPTY); + .setStack( j, ItemStack.EMPTY ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java index 1a66308b9..e3951e563 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java @@ -6,20 +6,14 @@ package dan200.computercraft.shared.turtle.upgrades; -import javax.annotation.Nonnull; - import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.TurtleUpgradeType; -import dan200.computercraft.api.turtle.TurtleVerb; +import dan200.computercraft.api.turtle.*; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.modem.ModemState; import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Identifier; @@ -28,105 +22,128 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; -public class TurtleModem extends AbstractTurtleUpgrade { +public class TurtleModem extends AbstractTurtleUpgrade +{ private final boolean advanced; - @Environment (EnvType.CLIENT) private ModelIdentifier m_leftOffModel; - @Environment (EnvType.CLIENT) private ModelIdentifier m_rightOffModel; - @Environment (EnvType.CLIENT) private ModelIdentifier m_leftOnModel; - @Environment (EnvType.CLIENT) private ModelIdentifier m_rightOnModel; + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_leftOffModel; + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_rightOffModel; + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_leftOnModel; + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_rightOnModel; - public TurtleModem(boolean advanced, Identifier id) { - super(id, - TurtleUpgradeType.PERIPHERAL, - advanced ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL); + public TurtleModem( boolean advanced, Identifier id ) + { + super( id, + TurtleUpgradeType.PERIPHERAL, + advanced ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL ); this.advanced = advanced; } @Override - public IPeripheral createPeripheral(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side) { - return new Peripheral(turtle, this.advanced); + public IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) + { + return new Peripheral( turtle, this.advanced ); } @Nonnull @Override - public TurtleCommandResult useTool(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction dir) { + public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction dir ) + { return TurtleCommandResult.failure(); } @Nonnull @Override - @Environment (EnvType.CLIENT) - public TransformedModel getModel(ITurtleAccess turtle, @Nonnull TurtleSide side) { + @Environment( EnvType.CLIENT ) + public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) + { this.loadModelLocations(); boolean active = false; - if (turtle != null) { - CompoundTag turtleNBT = turtle.getUpgradeNBTData(side); - active = turtleNBT.contains("active") && turtleNBT.getBoolean("active"); + if( turtle != null ) + { + CompoundTag turtleNBT = turtle.getUpgradeNBTData( side ); + active = turtleNBT.contains( "active" ) && turtleNBT.getBoolean( "active" ); } - return side == TurtleSide.LEFT ? TransformedModel.of(active ? this.m_leftOnModel : this.m_leftOffModel) : TransformedModel.of(active ? this.m_rightOnModel : this.m_rightOffModel); + return side == TurtleSide.LEFT ? TransformedModel.of( active ? this.m_leftOnModel : this.m_leftOffModel ) : TransformedModel.of( active ? this.m_rightOnModel : this.m_rightOffModel ); } - @Environment (EnvType.CLIENT) - private void loadModelLocations() { - if (this.m_leftOffModel == null) { - if (this.advanced) { - this.m_leftOffModel = new ModelIdentifier("computercraft:turtle_modem_advanced_off_left", "inventory"); - this.m_rightOffModel = new ModelIdentifier("computercraft:turtle_modem_advanced_off_right", "inventory"); - this.m_leftOnModel = new ModelIdentifier("computercraft:turtle_modem_advanced_on_left", "inventory"); - this.m_rightOnModel = new ModelIdentifier("computercraft:turtle_modem_advanced_on_right", "inventory"); - } else { - this.m_leftOffModel = new ModelIdentifier("computercraft:turtle_modem_normal_off_left", "inventory"); - this.m_rightOffModel = new ModelIdentifier("computercraft:turtle_modem_normal_off_right", "inventory"); - this.m_leftOnModel = new ModelIdentifier("computercraft:turtle_modem_normal_on_left", "inventory"); - this.m_rightOnModel = new ModelIdentifier("computercraft:turtle_modem_normal_on_right", "inventory"); + @Environment( EnvType.CLIENT ) + private void loadModelLocations() + { + if( this.m_leftOffModel == null ) + { + if( this.advanced ) + { + this.m_leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_left", "inventory" ); + this.m_rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_right", "inventory" ); + this.m_leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_left", "inventory" ); + this.m_rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_right", "inventory" ); + } + else + { + this.m_leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_left", "inventory" ); + this.m_rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_right", "inventory" ); + this.m_leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_left", "inventory" ); + this.m_rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_right", "inventory" ); } } } @Override - public void update(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side) { + public void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) + { // Advance the modem - if (!turtle.getWorld().isClient) { - IPeripheral peripheral = turtle.getPeripheral(side); - if (peripheral instanceof Peripheral) { + if( !turtle.getWorld().isClient ) + { + IPeripheral peripheral = turtle.getPeripheral( side ); + if( peripheral instanceof Peripheral ) + { ModemState state = ((Peripheral) peripheral).getModemState(); - if (state.pollChanged()) { - turtle.getUpgradeNBTData(side) - .putBoolean("active", state.isOpen()); - turtle.updateUpgradeNBTData(side); + if( state.pollChanged() ) + { + turtle.getUpgradeNBTData( side ) + .putBoolean( "active", state.isOpen() ); + turtle.updateUpgradeNBTData( side ); } } } } - private static class Peripheral extends WirelessModemPeripheral { + private static class Peripheral extends WirelessModemPeripheral + { private final ITurtleAccess turtle; - Peripheral(ITurtleAccess turtle, boolean advanced) { - super(new ModemState(), advanced); + Peripheral( ITurtleAccess turtle, boolean advanced ) + { + super( new ModemState(), advanced ); this.turtle = turtle; } @Nonnull @Override - public World getWorld() { + public World getWorld() + { return this.turtle.getWorld(); } @Nonnull @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { BlockPos turtlePos = this.turtle.getPosition(); - return new Vec3d(turtlePos.getX(), turtlePos.getY(), turtlePos.getZ()); + return new Vec3d( turtlePos.getX(), turtlePos.getY(), turtlePos.getZ() ); } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return this == other || (other instanceof Peripheral && ((Peripheral) other).turtle == this.turtle); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java index d60522d7f..79ce86663 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java @@ -6,15 +6,12 @@ package dan200.computercraft.shared.turtle.upgrades; -import javax.annotation.Nonnull; - import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleVerb; import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; import dan200.computercraft.shared.turtle.core.TurtlePlayer; - import net.minecraft.block.BlockState; import net.minecraft.block.Material; import net.minecraft.item.Item; @@ -24,35 +21,46 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public class TurtleShovel extends TurtleTool { - public TurtleShovel(Identifier id, String adjective, Item item) { - super(id, adjective, item); +import javax.annotation.Nonnull; + +public class TurtleShovel extends TurtleTool +{ + public TurtleShovel( Identifier id, String adjective, Item item ) + { + super( id, adjective, item ); } - public TurtleShovel(Identifier id, Item item) { - super(id, item); + public TurtleShovel( Identifier id, Item item ) + { + super( id, item ); } - public TurtleShovel(Identifier id, ItemStack craftItem, ItemStack toolItem) { - super(id, craftItem, toolItem); + public TurtleShovel( Identifier id, ItemStack craftItem, ItemStack toolItem ) + { + super( id, craftItem, toolItem ); } @Nonnull @Override - public TurtleCommandResult useTool(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction) { - if (verb == TurtleVerb.DIG) { + public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) + { + if( verb == TurtleVerb.DIG ) + { ItemStack shovel = this.item.copy(); - ItemStack remainder = TurtlePlaceCommand.deploy(shovel, turtle, direction, null, null); - if (remainder != shovel) { + ItemStack remainder = TurtlePlaceCommand.deploy( shovel, turtle, direction, null, null ); + if( remainder != shovel ) + { return TurtleCommandResult.success(); } } - return super.useTool(turtle, side, verb, direction); + return super.useTool( turtle, side, verb, direction ); } @Override - protected boolean canBreakBlock(BlockState state, World world, BlockPos pos, TurtlePlayer player) { - if (!super.canBreakBlock(state, world, pos, player)) { + protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) + { + if( !super.canBreakBlock( state, world, pos, player ) ) + { return false; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java index cd90b2699..187080a90 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java @@ -5,8 +5,6 @@ */ package dan200.computercraft.shared.turtle.upgrades; -import javax.annotation.Nonnull; - import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; @@ -15,74 +13,89 @@ import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleUpgradeType; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; +import javax.annotation.Nonnull; -public class TurtleSpeaker extends AbstractTurtleUpgrade { - @Environment (EnvType.CLIENT) private ModelIdentifier m_leftModel; - @Environment (EnvType.CLIENT) private ModelIdentifier m_rightModel; +public class TurtleSpeaker extends AbstractTurtleUpgrade +{ + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_leftModel; + @Environment( EnvType.CLIENT ) + private ModelIdentifier m_rightModel; - public TurtleSpeaker(Identifier id) { - super(id, TurtleUpgradeType.PERIPHERAL, ComputerCraftRegistry.ModBlocks.SPEAKER); + public TurtleSpeaker( Identifier id ) + { + super( id, TurtleUpgradeType.PERIPHERAL, ComputerCraftRegistry.ModBlocks.SPEAKER ); } @Override - public IPeripheral createPeripheral(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side) { - return new TurtleSpeaker.Peripheral(turtle); + public IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) + { + return new TurtleSpeaker.Peripheral( turtle ); } @Nonnull @Override - @Environment (EnvType.CLIENT) - public TransformedModel getModel(ITurtleAccess turtle, @Nonnull TurtleSide side) { + @Environment( EnvType.CLIENT ) + public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) + { this.loadModelLocations(); - return TransformedModel.of(side == TurtleSide.LEFT ? this.m_leftModel : this.m_rightModel); + return TransformedModel.of( side == TurtleSide.LEFT ? this.m_leftModel : this.m_rightModel ); } - @Environment (EnvType.CLIENT) - private void loadModelLocations() { - if (this.m_leftModel == null) { - this.m_leftModel = new ModelIdentifier("computercraft:turtle_speaker_upgrade_left", "inventory"); - this.m_rightModel = new ModelIdentifier("computercraft:turtle_speaker_upgrade_right", "inventory"); + @Environment( EnvType.CLIENT ) + private void loadModelLocations() + { + if( this.m_leftModel == null ) + { + this.m_leftModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_left", "inventory" ); + this.m_rightModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_right", "inventory" ); } } @Override - public void update(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide turtleSide) { - IPeripheral turtlePeripheral = turtle.getPeripheral(turtleSide); - if (turtlePeripheral instanceof Peripheral) { + public void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide turtleSide ) + { + IPeripheral turtlePeripheral = turtle.getPeripheral( turtleSide ); + if( turtlePeripheral instanceof Peripheral ) + { Peripheral peripheral = (Peripheral) turtlePeripheral; peripheral.update(); } } - private static class Peripheral extends SpeakerPeripheral { + private static class Peripheral extends SpeakerPeripheral + { ITurtleAccess turtle; - Peripheral(ITurtleAccess turtle) { + Peripheral( ITurtleAccess turtle ) + { this.turtle = turtle; } @Override - public World getWorld() { + public World getWorld() + { return this.turtle.getWorld(); } @Override - public Vec3d getPosition() { + public Vec3d getPosition() + { BlockPos pos = this.turtle.getPosition(); - return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); } @Override - public boolean equals(IPeripheral other) { + public boolean equals( IPeripheral other ) + { return this == other || (other instanceof Peripheral && this.turtle == ((Peripheral) other).turtle); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java index 61853c33f..7c41f9b46 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java @@ -7,7 +7,6 @@ package dan200.computercraft.shared.turtle.upgrades; import dan200.computercraft.shared.turtle.core.TurtlePlayer; - import net.minecraft.block.BlockState; import net.minecraft.block.Material; import net.minecraft.item.Item; @@ -16,27 +15,34 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class TurtleSword extends TurtleTool { - public TurtleSword(Identifier id, String adjective, Item item) { - super(id, adjective, item); +public class TurtleSword extends TurtleTool +{ + public TurtleSword( Identifier id, String adjective, Item item ) + { + super( id, adjective, item ); } - public TurtleSword(Identifier id, Item item) { - super(id, item); + public TurtleSword( Identifier id, Item item ) + { + super( id, item ); } - public TurtleSword(Identifier id, ItemStack craftItem, ItemStack toolItem) { - super(id, craftItem, toolItem); + public TurtleSword( Identifier id, ItemStack craftItem, ItemStack toolItem ) + { + super( id, craftItem, toolItem ); } @Override - protected float getDamageMultiplier() { + protected float getDamageMultiplier() + { return 9.0f; } @Override - protected boolean canBreakBlock(BlockState state, World world, BlockPos pos, TurtlePlayer player) { - if (!super.canBreakBlock(state, world, pos, player)) { + protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) + { + if( !super.canBreakBlock( state, world, pos, player ) ) + { return false; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index 2ba822b6f..45d63752b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -6,21 +6,9 @@ package dan200.computercraft.shared.turtle.upgrades; -import java.util.List; -import java.util.function.Function; - -import javax.annotation.Nonnull; - -import org.apache.commons.lang3.tuple.Pair; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.TurtleUpgradeType; -import dan200.computercraft.api.turtle.TurtleVerb; +import dan200.computercraft.api.turtle.*; import dan200.computercraft.api.turtle.event.TurtleAttackEvent; import dan200.computercraft.api.turtle.event.TurtleBlockEvent; import dan200.computercraft.api.turtle.event.TurtleEvent; @@ -31,6 +19,9 @@ import dan200.computercraft.shared.turtle.core.TurtlePlayer; import dan200.computercraft.shared.util.DropConsumer; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.WorldUtil; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.event.player.AttackEntityCallback; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -51,29 +42,34 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import org.apache.commons.lang3.tuple.Pair; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.event.player.AttackEntityCallback; +import javax.annotation.Nonnull; +import java.util.List; +import java.util.function.Function; -public class TurtleTool extends AbstractTurtleUpgrade { +public class TurtleTool extends AbstractTurtleUpgrade +{ protected final ItemStack item; private static final int TAG_LIST = 9; private static final int TAG_COMPOUND = 10; - public TurtleTool(Identifier id, String adjective, Item item) { - super(id, TurtleUpgradeType.TOOL, adjective, item); - this.item = new ItemStack(item); + public TurtleTool( Identifier id, String adjective, Item item ) + { + super( id, TurtleUpgradeType.TOOL, adjective, item ); + this.item = new ItemStack( item ); } - public TurtleTool(Identifier id, Item item) { - super(id, TurtleUpgradeType.TOOL, item); - this.item = new ItemStack(item); + public TurtleTool( Identifier id, Item item ) + { + super( id, TurtleUpgradeType.TOOL, item ); + this.item = new ItemStack( item ); } - public TurtleTool(Identifier id, ItemStack craftItem, ItemStack toolItem) { - super(id, TurtleUpgradeType.TOOL, craftItem); + public TurtleTool( Identifier id, ItemStack craftItem, ItemStack toolItem ) + { + super( id, TurtleUpgradeType.TOOL, craftItem ); this.item = toolItem; } @@ -97,58 +93,65 @@ public class TurtleTool extends AbstractTurtleUpgrade { @Nonnull @Override - public TurtleCommandResult useTool(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction) { - switch (verb) { - case ATTACK: - return this.attack(turtle, direction, side); - case DIG: - return this.dig(turtle, direction, side); - default: - return TurtleCommandResult.failure("Unsupported action"); + public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) + { + switch( verb ) + { + case ATTACK: + return this.attack( turtle, direction, side ); + case DIG: + return this.dig( turtle, direction, side ); + default: + return TurtleCommandResult.failure( "Unsupported action" ); } } @Nonnull @Override - @Environment (EnvType.CLIENT) - public TransformedModel getModel(ITurtleAccess turtle, @Nonnull TurtleSide side) { + @Environment( EnvType.CLIENT ) + public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) + { float xOffset = side == TurtleSide.LEFT ? -0.40625f : 0.40625f; - return TransformedModel.of(this.getCraftingItem(), new AffineTransformation(new Vector3f(xOffset + 1, 0, 1), Vector3f.POSITIVE_Y.getDegreesQuaternion(270), new Vector3f(1, 1, 1), Vector3f.POSITIVE_Z.getDegreesQuaternion(90))); + return TransformedModel.of( this.getCraftingItem(), new AffineTransformation( new Vector3f( xOffset + 1, 0, 1 ), Vector3f.POSITIVE_Y.getDegreesQuaternion( 270 ), new Vector3f( 1, 1, 1 ), Vector3f.POSITIVE_Z.getDegreesQuaternion( 90 ) ) ); } - private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side ) { + private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side ) + { // Create a fake player, and orient it appropriately World world = turtle.getWorld(); BlockPos position = turtle.getPosition(); BlockEntity turtleBlock = turtle instanceof TurtleBrain ? ((TurtleBrain) turtle).getOwner() : world.getBlockEntity( position ); if( turtleBlock == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." ); - final TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer(turtle, position, direction); + final TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, position, direction ); // See if there is an entity present Vec3d turtlePos = turtlePlayer.getPos(); - Vec3d rayDir = turtlePlayer.getRotationVec(1.0f); - Pair hit = WorldUtil.rayTraceEntities(world, turtlePos, rayDir, 1.5); - if (hit != null) { + Vec3d rayDir = turtlePlayer.getRotationVec( 1.0f ); + Pair hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 ); + if( hit != null ) + { // Load up the turtle's inventoryf ItemStack stackCopy = this.item.copy(); - turtlePlayer.loadInventory(stackCopy); + turtlePlayer.loadInventory( stackCopy ); Entity hitEntity = hit.getKey(); // Fire several events to ensure we have permissions. - if (AttackEntityCallback.EVENT.invoker() - .interact(turtlePlayer, - world, - Hand.MAIN_HAND, - hitEntity, - null) == ActionResult.FAIL || !hitEntity.isAttackable()) { - return TurtleCommandResult.failure("Nothing to attack here"); + if( AttackEntityCallback.EVENT.invoker() + .interact( turtlePlayer, + world, + Hand.MAIN_HAND, + hitEntity, + null ) == ActionResult.FAIL || !hitEntity.isAttackable() ) + { + return TurtleCommandResult.failure( "Nothing to attack here" ); } - TurtleAttackEvent attackEvent = new TurtleAttackEvent(turtle, turtlePlayer, hitEntity, this, side); - if (TurtleEvent.post(attackEvent)) { - return TurtleCommandResult.failure(attackEvent.getFailureMessage()); + TurtleAttackEvent attackEvent = new TurtleAttackEvent( turtle, turtlePlayer, hitEntity, this, side ); + if( TurtleEvent.post( attackEvent ) ) + { + return TurtleCommandResult.failure( attackEvent.getFailureMessage() ); } // Start claiming entity drops @@ -156,20 +159,27 @@ public class TurtleTool extends AbstractTurtleUpgrade { // Attack the entity boolean attacked = false; - if (!hitEntity.handleAttack(turtlePlayer)) { - float damage = (float) turtlePlayer.getAttributeValue(EntityAttributes.GENERIC_ATTACK_DAMAGE); + if( !hitEntity.handleAttack( turtlePlayer ) ) + { + float damage = (float) turtlePlayer.getAttributeValue( EntityAttributes.GENERIC_ATTACK_DAMAGE ); damage *= this.getDamageMultiplier(); - if (damage > 0.0f) { - DamageSource source = DamageSource.player(turtlePlayer); - if (hitEntity instanceof ArmorStandEntity) { + if( damage > 0.0f ) + { + DamageSource source = DamageSource.player( turtlePlayer ); + if( hitEntity instanceof ArmorStandEntity ) + { // Special case for armor stands: attack twice to guarantee destroy - hitEntity.damage(source, damage); - if (hitEntity.isAlive()) { - hitEntity.damage(source, damage); + hitEntity.damage( source, damage ); + if( hitEntity.isAlive() ) + { + hitEntity.damage( source, damage ); } attacked = true; - } else { - if (hitEntity.damage(source, damage)) { + } + else + { + if( hitEntity.damage( source, damage ) ) + { attacked = true; } } @@ -180,16 +190,18 @@ public class TurtleTool extends AbstractTurtleUpgrade { stopConsuming( turtleBlock, turtle ); // Put everything we collected into the turtles inventory, then return - if (attacked) { - turtlePlayer.unloadInventory(turtle); + if( attacked ) + { + turtlePlayer.unloadInventory( turtle ); return TurtleCommandResult.success(); } } - return TurtleCommandResult.failure("Nothing to attack here"); + return TurtleCommandResult.failure( "Nothing to attack here" ); } - private TurtleCommandResult dig(ITurtleAccess turtle, Direction direction, TurtleSide side) { + private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction, TurtleSide side ) + { // Get ready to dig World world = turtle.getWorld(); BlockPos turtlePosition = turtle.getPosition(); @@ -197,84 +209,96 @@ public class TurtleTool extends AbstractTurtleUpgrade { if( turtleBlock == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." ); - BlockPos blockPosition = turtlePosition.offset(direction); + BlockPos blockPosition = turtlePosition.offset( direction ); - if (world.isAir(blockPosition) || WorldUtil.isLiquidBlock(world, blockPosition)) { - return TurtleCommandResult.failure("Nothing to dig here"); + if( world.isAir( blockPosition ) || WorldUtil.isLiquidBlock( world, blockPosition ) ) + { + return TurtleCommandResult.failure( "Nothing to dig here" ); } - BlockState state = world.getBlockState(blockPosition); + BlockState state = world.getBlockState( blockPosition ); - TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer(turtle, turtlePosition, direction); - turtlePlayer.loadInventory(this.item.copy()); + TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, turtlePosition, direction ); + turtlePlayer.loadInventory( this.item.copy() ); - if (ComputerCraft.turtlesObeyBlockProtection) { - if (!TurtlePermissions.isBlockEditable(world, blockPosition, turtlePlayer)) { - return TurtleCommandResult.failure("Cannot break protected block"); + if( ComputerCraft.turtlesObeyBlockProtection ) + { + if( !TurtlePermissions.isBlockEditable( world, blockPosition, turtlePlayer ) ) + { + return TurtleCommandResult.failure( "Cannot break protected block" ); } } // Check if we can break the block - if (!this.canBreakBlock(state, world, blockPosition, turtlePlayer)) { - return TurtleCommandResult.failure("Unbreakable block detected"); + if( !this.canBreakBlock( state, world, blockPosition, turtlePlayer ) ) + { + return TurtleCommandResult.failure( "Unbreakable block detected" ); } // Fire the dig event, checking whether it was cancelled. - TurtleBlockEvent.Dig digEvent = new TurtleBlockEvent.Dig(turtle, turtlePlayer, world, blockPosition, state, this, side); - if (TurtleEvent.post(digEvent)) { - return TurtleCommandResult.failure(digEvent.getFailureMessage()); + TurtleBlockEvent.Dig digEvent = new TurtleBlockEvent.Dig( turtle, turtlePlayer, world, blockPosition, state, this, side ); + if( TurtleEvent.post( digEvent ) ) + { + return TurtleCommandResult.failure( digEvent.getFailureMessage() ); } // Consume the items the block drops DropConsumer.set( world, blockPosition, turtleDropConsumer( turtleBlock, turtle ) ); - BlockEntity tile = world.getBlockEntity(blockPosition); + BlockEntity tile = world.getBlockEntity( blockPosition ); // Much of this logic comes from PlayerInteractionManager#tryHarvestBlock, so it's a good idea // to consult there before making any changes. // Play the destruction sound and particles - world.syncWorldEvent(2001, blockPosition, Block.getRawIdFromState(state)); + world.syncWorldEvent( 2001, blockPosition, Block.getRawIdFromState( state ) ); // Destroy the block state.getBlock() - .onBreak(world, blockPosition, state, turtlePlayer); - if (world.removeBlock(blockPosition, false)) { + .onBreak( world, blockPosition, state, turtlePlayer ); + if( world.removeBlock( blockPosition, false ) ) + { state.getBlock() - .onBroken(world, blockPosition, state); - if (turtlePlayer.isUsingEffectiveTool(state)) { + .onBroken( world, blockPosition, state ); + if( turtlePlayer.isUsingEffectiveTool( state ) ) + { state.getBlock() - .afterBreak(world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandStack()); + .afterBreak( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandStack() ); } } - stopConsuming(turtleBlock, turtle); + stopConsuming( turtleBlock, turtle ); return TurtleCommandResult.success(); } - private static Function turtleDropConsumer(BlockEntity turtleBlock, ITurtleAccess turtle) { - return drop -> turtleBlock.isRemoved() ? drop : InventoryUtil.storeItems(drop, turtle.getItemHandler(), turtle.getSelectedSlot()); + private static Function turtleDropConsumer( BlockEntity turtleBlock, ITurtleAccess turtle ) + { + return drop -> turtleBlock.isRemoved() ? drop : InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ); } - protected float getDamageMultiplier() { + protected float getDamageMultiplier() + { return 3.0f; } - private static void stopConsuming(BlockEntity turtleBlock, ITurtleAccess turtle) { + private static void stopConsuming( BlockEntity turtleBlock, ITurtleAccess turtle ) + { Direction direction = turtleBlock.isRemoved() ? null : turtle.getDirection().getOpposite(); List extra = DropConsumer.clear(); - for (ItemStack remainder : extra) { - WorldUtil.dropItemStack(remainder, - turtle.getWorld(), - turtle.getPosition(), - direction); + for( ItemStack remainder : extra ) + { + WorldUtil.dropItemStack( remainder, + turtle.getWorld(), + turtle.getPosition(), + direction ); } } - protected boolean canBreakBlock(BlockState state, World world, BlockPos pos, TurtlePlayer player) { + protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) + { Block block = state.getBlock(); - return !state.isAir() && block != Blocks.BEDROCK && state.calcBlockBreakingDelta(player, world, pos) > 0; + return !state.isAir() && block != Blocks.BEDROCK && state.calcBlockBreakingDelta( player, world, pos ) > 0; } } diff --git a/src/main/java/dan200/computercraft/shared/util/Colour.java b/src/main/java/dan200/computercraft/shared/util/Colour.java index 1bf145d8a..0f7c2840f 100644 --- a/src/main/java/dan200/computercraft/shared/util/Colour.java +++ b/src/main/java/dan200/computercraft/shared/util/Colour.java @@ -6,44 +6,50 @@ package dan200.computercraft.shared.util; -public enum Colour { - BLACK(0x111111), - RED(0xcc4c4c), - GREEN(0x57A64E), - BROWN(0x7f664c), - BLUE(0x3366cc), - PURPLE(0xb266e5), - CYAN(0x4c99b2), - LIGHT_GREY(0x999999), - GREY(0x4c4c4c), - PINK(0xf2b2cc), - LIME(0x7fcc19), - YELLOW(0xdede6c), - LIGHT_BLUE(0x99b2f2), - MAGENTA(0xe57fd8), - ORANGE(0xf2b233), - WHITE(0xf0f0f0); +public enum Colour +{ + BLACK( 0x111111 ), + RED( 0xcc4c4c ), + GREEN( 0x57A64E ), + BROWN( 0x7f664c ), + BLUE( 0x3366cc ), + PURPLE( 0xb266e5 ), + CYAN( 0x4c99b2 ), + LIGHT_GREY( 0x999999 ), + GREY( 0x4c4c4c ), + PINK( 0xf2b2cc ), + LIME( 0x7fcc19 ), + YELLOW( 0xdede6c ), + LIGHT_BLUE( 0x99b2f2 ), + MAGENTA( 0xe57fd8 ), + ORANGE( 0xf2b233 ), + WHITE( 0xf0f0f0 ); public static final Colour[] VALUES = values(); private final int hex; private final float[] rgb; - Colour(int hex) { + Colour( int hex ) + { this.hex = hex; this.rgb = new float[] { ((hex >> 16) & 0xFF) / 255.0f, ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f, - }; + }; } - public static Colour fromInt(int colour) { + public static Colour fromInt( int colour ) + { return colour >= 0 && colour < 16 ? Colour.VALUES[colour] : null; } - public static Colour fromHex(int colour) { - for (Colour entry : VALUES) { - if (entry.getHex() == colour) { + public static Colour fromHex( int colour ) + { + for( Colour entry : VALUES ) + { + if( entry.getHex() == colour ) + { return entry; } } @@ -51,31 +57,38 @@ public enum Colour { return null; } - public int getHex() { + public int getHex() + { return this.hex; } - public Colour getNext() { + public Colour getNext() + { return VALUES[(this.ordinal() + 1) % 16]; } - public Colour getPrevious() { + public Colour getPrevious() + { return VALUES[(this.ordinal() + 15) % 16]; } - public float[] getRGB() { + public float[] getRGB() + { return this.rgb; } - public float getR() { + public float getR() + { return this.rgb[0]; } - public float getG() { + public float getG() + { return this.rgb[1]; } - public float getB() { + public float getB() + { return this.rgb[2]; } } diff --git a/src/main/java/dan200/computercraft/shared/util/ColourTracker.java b/src/main/java/dan200/computercraft/shared/util/ColourTracker.java index 25daa65e2..3bfe9d062 100644 --- a/src/main/java/dan200/computercraft/shared/util/ColourTracker.java +++ b/src/main/java/dan200/computercraft/shared/util/ColourTracker.java @@ -11,19 +11,22 @@ import net.minecraft.util.DyeColor; /** * A reimplementation of the colour system in {@link ArmorDyeRecipe}, but bundled together as an object. */ -public class ColourTracker { +public class ColourTracker +{ private int total; private int totalR; private int totalG; private int totalB; private int count; - public void addColour(float r, float g, float b) { - this.addColour((int) (r * 255), (int) (g * 255), (int) (b * 255)); + public void addColour( float r, float g, float b ) + { + this.addColour( (int) (r * 255), (int) (g * 255), (int) (b * 255) ); } - public void addColour(int r, int g, int b) { - this.total += Math.max(r, Math.max(g, b)); + public void addColour( int r, int g, int b ) + { + this.total += Math.max( r, Math.max( g, b ) ); this.totalR += r; this.totalG += g; this.totalB += b; @@ -41,13 +44,14 @@ public class ColourTracker { return count > 0; } - public int getColour() { + public int getColour() + { int avgR = this.totalR / this.count; int avgG = this.totalG / this.count; int avgB = this.totalB / this.count; float avgTotal = (float) this.total / this.count; - float avgMax = Math.max(avgR, Math.max(avgG, avgB)); + float avgMax = Math.max( avgR, Math.max( avgG, avgB ) ); avgR = (int) (avgR * avgTotal / avgMax); avgG = (int) (avgG * avgTotal / avgMax); avgB = (int) (avgB * avgTotal / avgMax); diff --git a/src/main/java/dan200/computercraft/shared/util/ColourUtils.java b/src/main/java/dan200/computercraft/shared/util/ColourUtils.java index a89affa27..92a1a13fc 100644 --- a/src/main/java/dan200/computercraft/shared/util/ColourUtils.java +++ b/src/main/java/dan200/computercraft/shared/util/ColourUtils.java @@ -6,18 +6,20 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nullable; - import net.minecraft.item.DyeItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.DyeColor; -public final class ColourUtils { +import javax.annotation.Nullable; + +public final class ColourUtils +{ @Nullable private ColourUtils() {} - public static DyeColor getStackColour(ItemStack stack) { + public static DyeColor getStackColour( ItemStack stack ) + { Item item = stack.getItem(); return item instanceof DyeItem ? ((DyeItem) item).getColor() : null; } diff --git a/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java b/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java index a1d972d19..fe13c12ba 100644 --- a/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java +++ b/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java @@ -5,40 +5,50 @@ */ package dan200.computercraft.shared.util; -import com.electronwill.nightconfig.core.Config; import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.Config; import com.electronwill.nightconfig.core.ConfigSpec; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static com.electronwill.nightconfig.core.utils.StringUtils.split; -public class CommentedConfigSpec extends ConfigSpec { +public class CommentedConfigSpec extends ConfigSpec +{ private final Map, String> comments = new HashMap<>(); - public void comment(List path, String comment) { - comments.put(path, comment); + public void comment( List path, String comment ) + { + comments.put( path, comment ); } - public void comment(String path, String comment) { - comment(split(path, '.'), comment); + public void comment( String path, String comment ) + { + comment( split( path, '.' ), comment ); } - public int correct(Config config) { - return correct(config, (action, path, incorrectValue, correctedValue) -> {}); + public int correct( Config config ) + { + return correct( config, ( action, path, incorrectValue, correctedValue ) -> {} ); } - public int correct(Config config, ConfigSpec.CorrectionListener listener) { - int corrections = super.correct(config, listener); - if(config instanceof CommentedConfig) { - insertComments((CommentedConfig) config); + public int correct( Config config, ConfigSpec.CorrectionListener listener ) + { + int corrections = super.correct( config, listener ); + if( config instanceof CommentedConfig ) + { + insertComments( (CommentedConfig) config ); } return corrections; } - private void insertComments(CommentedConfig config) { - for(Map.Entry, String> entry : comments.entrySet()) { - config.setComment(entry.getKey(), entry.getValue()); + private void insertComments( CommentedConfig config ) + { + for( Map.Entry, String> entry : comments.entrySet() ) + { + config.setComment( entry.getKey(), entry.getValue() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/util/Config.java b/src/main/java/dan200/computercraft/shared/util/Config.java index fdf35bd77..b9fc34156 100644 --- a/src/main/java/dan200/computercraft/shared/util/Config.java +++ b/src/main/java/dan200/computercraft/shared/util/Config.java @@ -5,7 +5,10 @@ */ package dan200.computercraft.shared.util; -import com.electronwill.nightconfig.core.*; +import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.ConfigSpec; +import com.electronwill.nightconfig.core.EnumGetMethod; +import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.electronwill.nightconfig.core.file.FileNotFoundAction; import com.google.common.base.CaseFormat; @@ -27,7 +30,8 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -public class Config { +public class Config +{ private static final int MODEM_MAX_RANGE = 100000; public static final String TRANSLATION_PREFIX = "gui.computercraft.config."; @@ -38,327 +42,346 @@ public class Config { public static CommentedConfig serverConfig; public static CommentedConfig clientConfig; - private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath("serverconfig"); + private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath( "serverconfig" ); private static final String serverFileName = "computercraft-server.toml"; - private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve("computercraft-client.toml"); + private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve( "computercraft-client.toml" ); - private Config() { + private Config() + { } - static { - System.setProperty("nightconfig.preserveInsertionOrder", "true"); + static + { + System.setProperty( "nightconfig.preserveInsertionOrder", "true" ); serverSpec = new CommentedConfigSpec(); { // General computers - serverSpec.comment("computer_space_limit", - "The disk space limit for computers and turtles, in bytes"); - serverSpec.define("computer_space_limit", ComputerCraft.computerSpaceLimit); + serverSpec.comment( "computer_space_limit", + "The disk space limit for computers and turtles, in bytes" ); + serverSpec.define( "computer_space_limit", ComputerCraft.computerSpaceLimit ); - serverSpec.comment("floppy_space_limit", - "The disk space limit for floppy disks, in bytes"); - serverSpec.define("floppy_space_limit", ComputerCraft.floppySpaceLimit); + serverSpec.comment( "floppy_space_limit", + "The disk space limit for floppy disks, in bytes" ); + serverSpec.define( "floppy_space_limit", ComputerCraft.floppySpaceLimit ); - serverSpec.comment("maximum_open_files", - "Set how many files a computer can have open at the same time. Set to 0 for unlimited."); - serverSpec.defineInRange("maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE); + serverSpec.comment( "maximum_open_files", + "Set how many files a computer can have open at the same time. Set to 0 for unlimited." ); + serverSpec.defineInRange( "maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE ); - serverSpec.comment("disable_lua51_features", - "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + - "Useful for ensuring forward compatibility of your programs now."); - serverSpec.define("disable_lua51_features", ComputerCraft.disableLua51Features); + serverSpec.comment( "disable_lua51_features", + "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + + "Useful for ensuring forward compatibility of your programs now." ); + serverSpec.define( "disable_lua51_features", ComputerCraft.disableLua51Features ); - serverSpec.comment("default_computer_settings", - "A comma separated list of default system settings to set on new computers. Example: " + + serverSpec.comment( "default_computer_settings", + "A comma separated list of default system settings to set on new computers. Example: " + "\"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all " + - "autocompletion"); - serverSpec.define("default_computer_settings", ComputerCraft.defaultComputerSettings); + "autocompletion" ); + serverSpec.define( "default_computer_settings", ComputerCraft.defaultComputerSettings ); - serverSpec.comment("debug_enabled", - "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players."); - serverSpec.define("debug_enabled", ComputerCraft.debugEnable); + serverSpec.comment( "debug_enabled", + "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players." ); + serverSpec.define( "debug_enabled", ComputerCraft.debugEnable ); - serverSpec.comment("log_computer_errors", - "Log exceptions thrown by peripherals and other Lua objects.\n" + - "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods."); - serverSpec.define("log_computer_errors", ComputerCraft.logComputerErrors); + serverSpec.comment( "log_computer_errors", + "Log exceptions thrown by peripherals and other Lua objects.\n" + + "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods." ); + serverSpec.define( "log_computer_errors", ComputerCraft.logComputerErrors ); - serverSpec.comment("command_require_creative", - "Require players to be in creative mode and be opped in order to interact with command computers." + - "This is the default behaviour for vanilla's Command blocks."); - serverSpec.define("command_require_creative", ComputerCraft.commandRequireCreative); + serverSpec.comment( "command_require_creative", + "Require players to be in creative mode and be opped in order to interact with command computers." + + "This is the default behaviour for vanilla's Command blocks." ); + serverSpec.define( "command_require_creative", ComputerCraft.commandRequireCreative ); } { // Execution - serverSpec.comment("execution", - "Controls execution behaviour of computers. This is largely intended for fine-tuning " + - "servers, and generally shouldn't need to be touched"); + serverSpec.comment( "execution", + "Controls execution behaviour of computers. This is largely intended for fine-tuning " + + "servers, and generally shouldn't need to be touched" ); - serverSpec.comment("execution.computer_threads", - "Set the number of threads computers can run on. A higher number means more computers can run " + + serverSpec.comment( "execution.computer_threads", + "Set the number of threads computers can run on. A higher number means more computers can run " + "at once, but may induce lag.\n" + - "Please note that some mods may not work with a thread count higher than 1. Use with caution."); - serverSpec.defineInRange("execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE); + "Please note that some mods may not work with a thread count higher than 1. Use with caution." ); + serverSpec.defineInRange( "execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE ); - serverSpec.comment("execution.max_main_global_time", - "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + + serverSpec.comment( "execution.max_main_global_time", + "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time."); - serverSpec.defineInRange("execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE); + "- this aims to be the upper bound of the average time." ); + serverSpec.defineInRange( "execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE ); - serverSpec.comment("execution.max_main_computer_time", - "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + + serverSpec.comment( "execution.max_main_computer_time", + "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time."); - serverSpec.defineInRange("execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE); + "- this aims to be the upper bound of the average time." ); + serverSpec.defineInRange( "execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE ); } { // HTTP - serverSpec.comment("http", "Controls the HTTP API"); + serverSpec.comment( "http", "Controls the HTTP API" ); - serverSpec.comment("http.enabled", - "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)."); - serverSpec.define("http.enabled", ComputerCraft.httpEnabled); + serverSpec.comment( "http.enabled", + "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)." ); + serverSpec.define( "http.enabled", ComputerCraft.httpEnabled ); - serverSpec.comment("http.websocket_enabled", - "Enable use of http websockets. This requires the \"http_enable\" option to also be true."); - serverSpec.define("http.websocket_enabled", ComputerCraft.httpWebsocketEnabled); + serverSpec.comment( "http.websocket_enabled", + "Enable use of http websockets. This requires the \"http_enable\" option to also be true." ); + serverSpec.define( "http.websocket_enabled", ComputerCraft.httpWebsocketEnabled ); - serverSpec.comment("http.rules", - "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + + serverSpec.comment( "http.rules", + "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + "Each rule is an item with a 'host' to match against, and a series of properties. " + "The host may be a domain name (\"pastebin.com\"),\n" + - "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked."); - serverSpec.defineList("http.rules", Arrays.asList( - AddressRuleConfig.makeRule("$private", Action.DENY), - AddressRuleConfig.makeRule("*", Action.ALLOW) - ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule((UnmodifiableConfig) x)); + "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked." ); + serverSpec.defineList( "http.rules", Arrays.asList( + AddressRuleConfig.makeRule( "$private", Action.DENY ), + AddressRuleConfig.makeRule( "*", Action.ALLOW ) + ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule( (UnmodifiableConfig) x ) ); - serverSpec.comment("http.max_requests", - "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited."); - serverSpec.defineInRange("http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE); + serverSpec.comment( "http.max_requests", + "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited." ); + serverSpec.defineInRange( "http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE ); - serverSpec.comment("http.max_websockets", - "The number of websockets a computer can have open at one time. Set to 0 for unlimited."); - serverSpec.defineInRange("http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE); + serverSpec.comment( "http.max_websockets", + "The number of websockets a computer can have open at one time. Set to 0 for unlimited." ); + serverSpec.defineInRange( "http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE ); } { // Peripherals - serverSpec.comment("peripheral", "Various options relating to peripherals."); + serverSpec.comment( "peripheral", "Various options relating to peripherals." ); - serverSpec.comment("peripheral.command_block_enabled", - "Enable Command Block peripheral support"); - serverSpec.define("peripheral.command_block_enabled", ComputerCraft.enableCommandBlock); + serverSpec.comment( "peripheral.command_block_enabled", + "Enable Command Block peripheral support" ); + serverSpec.define( "peripheral.command_block_enabled", ComputerCraft.enableCommandBlock ); - serverSpec.comment("peripheral.modem_range", - "The range of Wireless Modems at low altitude in clear weather, in meters"); - serverSpec.defineInRange("peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_range", + "The range of Wireless Modems at low altitude in clear weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.modem_high_altitude_range", - "The range of Wireless Modems at maximum altitude in clear weather, in meters"); - serverSpec.defineInRange("peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_high_altitude_range", + "The range of Wireless Modems at maximum altitude in clear weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.modem_range_during_storm", - "The range of Wireless Modems at low altitude in stormy weather, in meters"); - serverSpec.defineInRange("peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_range_during_storm", + "The range of Wireless Modems at low altitude in stormy weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.modem_high_altitude_range_during_storm", - "The range of Wireless Modems at maximum altitude in stormy weather, in meters"); - serverSpec.defineInRange("peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_high_altitude_range_during_storm", + "The range of Wireless Modems at maximum altitude in stormy weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.max_notes_per_tick", - "Maximum amount of notes a speaker can play at once"); - serverSpec.defineInRange("peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE); + serverSpec.comment( "peripheral.max_notes_per_tick", + "Maximum amount of notes a speaker can play at once" ); + serverSpec.defineInRange( "peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE ); - serverSpec.comment("peripheral.monitor_bandwidth", - "The limit to how much monitor data can be sent *per tick*. Note:\n" + + serverSpec.comment( "peripheral.monitor_bandwidth", + "The limit to how much monitor data can be sent *per tick*. Note:\n" + " - Bandwidth is measured before compression, so the data sent to the client is smaller.\n" + " - This ignores the number of players a packet is sent to. Updating a monitor for one player consumes " + "the same bandwidth limit as sending to 20.\n" + " - A full sized monitor sends ~25kb of data. So the default (1MB) allows for ~40 monitors to be updated " + "in a single tick. \n" + - "Set to 0 to disable."); - serverSpec.defineInRange("peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE); + "Set to 0 to disable." ); + serverSpec.defineInRange( "peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE ); } { // Turtles - serverSpec.comment("turtle", "Various options relating to turtles."); + serverSpec.comment( "turtle", "Various options relating to turtles." ); - serverSpec.comment("turtle.need_fuel", - "Set whether Turtles require fuel to move"); - serverSpec.define("turtle.need_fuel", ComputerCraft.turtlesNeedFuel); + serverSpec.comment( "turtle.need_fuel", + "Set whether Turtles require fuel to move" ); + serverSpec.define( "turtle.need_fuel", ComputerCraft.turtlesNeedFuel ); - serverSpec.comment("turtle.normal_fuel_limit", "The fuel limit for Turtles"); - serverSpec.defineInRange("turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE); + serverSpec.comment( "turtle.normal_fuel_limit", "The fuel limit for Turtles" ); + serverSpec.defineInRange( "turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE ); - serverSpec.comment("turtle.advanced_fuel_limit", - "The fuel limit for Advanced Turtles"); - serverSpec.defineInRange("turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE); + serverSpec.comment( "turtle.advanced_fuel_limit", + "The fuel limit for Advanced Turtles" ); + serverSpec.defineInRange( "turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE ); - serverSpec.comment("turtle.obey_block_protection", - "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)"); - serverSpec.define("turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection); + serverSpec.comment( "turtle.obey_block_protection", + "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)" ); + serverSpec.define( "turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection ); - serverSpec.comment("turtle.can_push", - "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so"); - serverSpec.define("turtle.can_push", ComputerCraft.turtlesCanPush); + serverSpec.comment( "turtle.can_push", + "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so" ); + serverSpec.define( "turtle.can_push", ComputerCraft.turtlesCanPush ); - serverSpec.comment("turtle.disabled_actions", - "A list of turtle actions which are disabled."); - serverSpec.defineList("turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction((String) x) != null); + serverSpec.comment( "turtle.disabled_actions", + "A list of turtle actions which are disabled." ); + serverSpec.defineList( "turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction( (String) x ) != null ); } { - serverSpec.comment("term_sizes", "Configure the size of various computer's terminals.\n" + - "Larger terminals require more bandwidth, so use with care."); + serverSpec.comment( "term_sizes", "Configure the size of various computer's terminals.\n" + + "Larger terminals require more bandwidth, so use with care." ); - serverSpec.comment("term_sizes.computer", "Terminal size of computers"); - serverSpec.defineInRange("term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255); - serverSpec.defineInRange("term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255); + serverSpec.comment( "term_sizes.computer", "Terminal size of computers" ); + serverSpec.defineInRange( "term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255 ); + serverSpec.defineInRange( "term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255 ); - serverSpec.comment("term_sizes.pocket_computer", "Terminal size of pocket computers"); - serverSpec.defineInRange("term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255); - serverSpec.defineInRange("term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255); + serverSpec.comment( "term_sizes.pocket_computer", "Terminal size of pocket computers" ); + serverSpec.defineInRange( "term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255 ); + serverSpec.defineInRange( "term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255 ); - serverSpec.comment("term_sizes.monitor", "Maximum size of monitors (in blocks)"); - serverSpec.defineInRange("term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32); - serverSpec.defineInRange("term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32); + serverSpec.comment( "term_sizes.monitor", "Maximum size of monitors (in blocks)" ); + serverSpec.defineInRange( "term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32 ); + serverSpec.defineInRange( "term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32 ); } clientSpec = new CommentedConfigSpec(); - clientSpec.comment("monitor_renderer", - "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + - "monitors have performance issues, you may wish to experiment with alternative renderers."); - clientSpec.defineRestrictedEnum("monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf(MonitorRenderer.class), EnumGetMethod.NAME_IGNORECASE); + clientSpec.comment( "monitor_renderer", + "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + + "monitors have performance issues, you may wish to experiment with alternative renderers." ); + clientSpec.defineRestrictedEnum( "monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf( MonitorRenderer.class ), EnumGetMethod.NAME_IGNORECASE ); - clientSpec.comment("monitor_distance", - "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + + clientSpec.comment( "monitor_distance", + "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + "but may be extended if you wish to build larger monitors." ); - clientSpec.defineInRange("monitor_distance", 64, 16, 1024); + clientSpec.defineInRange( "monitor_distance", 64, 16, 1024 ); } - private static final FileNotFoundAction MAKE_DIRECTORIES = (file, configFormat) -> { - Files.createDirectories(file.getParent()); - Files.createFile(file); - configFormat.initEmptyFile(file); + private static final FileNotFoundAction MAKE_DIRECTORIES = ( file, configFormat ) -> { + Files.createDirectories( file.getParent() ); + Files.createFile( file ); + configFormat.initEmptyFile( file ); return false; }; - private static CommentedFileConfig buildFileConfig(Path path) { - return CommentedFileConfig.builder(path) - .onFileNotFound(MAKE_DIRECTORIES) - .preserveInsertionOrder() - .build(); + private static CommentedFileConfig buildFileConfig( Path path ) + { + return CommentedFileConfig.builder( path ) + .onFileNotFound( MAKE_DIRECTORIES ) + .preserveInsertionOrder() + .build(); } - public static void serverStarting(MinecraftServer server) { - Path serverPath = server.getSavePath(serverDir).resolve(serverFileName); + public static void serverStarting( MinecraftServer server ) + { + Path serverPath = server.getSavePath( serverDir ).resolve( serverFileName ); - try(CommentedFileConfig config = buildFileConfig(serverPath)) { + try( CommentedFileConfig config = buildFileConfig( serverPath ) ) + { config.load(); - serverSpec.correct(config, Config::correctionListener); + serverSpec.correct( config, Config::correctionListener ); config.save(); serverConfig = config; sync(); } } - public static void serverStopping(MinecraftServer server) { + public static void serverStopping( MinecraftServer server ) + { serverConfig = null; } - public static void clientStarted(MinecraftClient client) { - try (CommentedFileConfig config = buildFileConfig(clientPath)) { + public static void clientStarted( MinecraftClient client ) + { + try( CommentedFileConfig config = buildFileConfig( clientPath ) ) + { config.load(); - clientSpec.correct(config, Config::correctionListener); + clientSpec.correct( config, Config::correctionListener ); config.save(); clientConfig = config; sync(); } } - private static void correctionListener(ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue) { - String key = String.join(".", path); - switch(action) { + private static void correctionListener( ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue ) + { + String key = String.join( ".", path ); + switch( action ) + { case ADD: - ComputerCraft.log.warn("Config key {} missing -> added default value.", key); break; + ComputerCraft.log.warn( "Config key {} missing -> added default value.", key ); + break; case REMOVE: - ComputerCraft.log.warn("Config key {} not defined -> removed from config.", key); break; + ComputerCraft.log.warn( "Config key {} not defined -> removed from config.", key ); + break; case REPLACE: - ComputerCraft.log.warn("Config key {} not valid -> replaced with default value.", key); + ComputerCraft.log.warn( "Config key {} not valid -> replaced with default value.", key ); } } - public static void sync() { - if(serverConfig != null) { + public static void sync() + { + if( serverConfig != null ) + { // General - ComputerCraft.computerSpaceLimit = serverConfig.get("computer_space_limit"); - ComputerCraft.floppySpaceLimit = serverConfig.get("floppy_space_limit"); - ComputerCraft.maximumFilesOpen = serverConfig.get("maximum_open_files"); - ComputerCraft.disableLua51Features = serverConfig.get("disable_lua51_features"); - ComputerCraft.defaultComputerSettings = serverConfig.get("default_computer_settings"); - ComputerCraft.debugEnable = serverConfig.get("debug_enabled"); - ComputerCraft.logComputerErrors = serverConfig.get("log_computer_errors"); - ComputerCraft.commandRequireCreative = serverConfig.get("command_require_creative"); + ComputerCraft.computerSpaceLimit = serverConfig.get( "computer_space_limit" ); + ComputerCraft.floppySpaceLimit = serverConfig.get( "floppy_space_limit" ); + ComputerCraft.maximumFilesOpen = serverConfig.get( "maximum_open_files" ); + ComputerCraft.disableLua51Features = serverConfig.get( "disable_lua51_features" ); + ComputerCraft.defaultComputerSettings = serverConfig.get( "default_computer_settings" ); + ComputerCraft.debugEnable = serverConfig.get( "debug_enabled" ); + ComputerCraft.logComputerErrors = serverConfig.get( "log_computer_errors" ); + ComputerCraft.commandRequireCreative = serverConfig.get( "command_require_creative" ); // Execution - ComputerCraft.computerThreads = serverConfig.get("execution.computer_threads"); - ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_global_time")); - ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_computer_time")); + ComputerCraft.computerThreads = serverConfig.get( "execution.computer_threads" ); + ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_global_time" ) ); + ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_computer_time" ) ); // HTTP - ComputerCraft.httpEnabled = serverConfig.get("http.enabled"); - ComputerCraft.httpWebsocketEnabled = serverConfig.get("http.websocket_enabled"); - ComputerCraft.httpRules = serverConfig.>get("http.rules").stream().map(AddressRuleConfig::parseRule) - .filter(Objects::nonNull).collect(Collectors.toList()); - ComputerCraft.httpMaxRequests = serverConfig.get("http.max_requests"); - ComputerCraft.httpMaxWebsockets = serverConfig.get("http.max_websockets"); + ComputerCraft.httpEnabled = serverConfig.get( "http.enabled" ); + ComputerCraft.httpWebsocketEnabled = serverConfig.get( "http.websocket_enabled" ); + ComputerCraft.httpRules = serverConfig.>get( "http.rules" ).stream().map( AddressRuleConfig::parseRule ) + .filter( Objects::nonNull ).collect( Collectors.toList() ); + ComputerCraft.httpMaxRequests = serverConfig.get( "http.max_requests" ); + ComputerCraft.httpMaxWebsockets = serverConfig.get( "http.max_websockets" ); // Peripherals - ComputerCraft.enableCommandBlock = serverConfig.get("peripheral.command_block_enabled"); - ComputerCraft.modemRange = serverConfig.get("peripheral.modem_range"); - ComputerCraft.modemHighAltitudeRange = serverConfig.get("peripheral.modem_high_altitude_range"); - ComputerCraft.modemRangeDuringStorm = serverConfig.get("peripheral.modem_range_during_storm"); - ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get("peripheral.modem_high_altitude_range_during_storm"); - ComputerCraft.maxNotesPerTick = serverConfig.get("peripheral.max_notes_per_tick"); - ComputerCraft.monitorBandwidth = serverConfig.get("peripheral.monitor_bandwidth"); + ComputerCraft.enableCommandBlock = serverConfig.get( "peripheral.command_block_enabled" ); + ComputerCraft.modemRange = serverConfig.get( "peripheral.modem_range" ); + ComputerCraft.modemHighAltitudeRange = serverConfig.get( "peripheral.modem_high_altitude_range" ); + ComputerCraft.modemRangeDuringStorm = serverConfig.get( "peripheral.modem_range_during_storm" ); + ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get( "peripheral.modem_high_altitude_range_during_storm" ); + ComputerCraft.maxNotesPerTick = serverConfig.get( "peripheral.max_notes_per_tick" ); + ComputerCraft.monitorBandwidth = serverConfig.get( "peripheral.monitor_bandwidth" ); // Turtles - ComputerCraft.turtlesNeedFuel = serverConfig.get("turtle.need_fuel"); - ComputerCraft.turtleFuelLimit = serverConfig.get("turtle.normal_fuel_limit"); - ComputerCraft.advancedTurtleFuelLimit = serverConfig.get("turtle.advanced_fuel_limit"); - ComputerCraft.turtlesObeyBlockProtection = serverConfig.get("turtle.obey_block_protection"); - ComputerCraft.turtlesCanPush = serverConfig.get("turtle.can_push"); + ComputerCraft.turtlesNeedFuel = serverConfig.get( "turtle.need_fuel" ); + ComputerCraft.turtleFuelLimit = serverConfig.get( "turtle.normal_fuel_limit" ); + ComputerCraft.advancedTurtleFuelLimit = serverConfig.get( "turtle.advanced_fuel_limit" ); + ComputerCraft.turtlesObeyBlockProtection = serverConfig.get( "turtle.obey_block_protection" ); + ComputerCraft.turtlesCanPush = serverConfig.get( "turtle.can_push" ); ComputerCraft.turtleDisabledActions.clear(); - for(String value : serverConfig.>get("turtle.disabled_actions")) { - ComputerCraft.turtleDisabledActions.add(getAction(value)); + for( String value : serverConfig.>get( "turtle.disabled_actions" ) ) + { + ComputerCraft.turtleDisabledActions.add( getAction( value ) ); } // Terminal Size - ComputerCraft.computerTermWidth = serverConfig.get("term_sizes.computer.width"); - ComputerCraft.computerTermHeight = serverConfig.get("term_sizes.computer.height"); - ComputerCraft.pocketTermWidth = serverConfig.get("term_sizes.pocket_computer.width"); - ComputerCraft.pocketTermHeight = serverConfig.get("term_sizes.pocket_computer.height"); - ComputerCraft.monitorWidth = serverConfig.get("term_sizes.monitor.width"); - ComputerCraft.monitorHeight = serverConfig.get("term_sizes.monitor.height"); + ComputerCraft.computerTermWidth = serverConfig.get( "term_sizes.computer.width" ); + ComputerCraft.computerTermHeight = serverConfig.get( "term_sizes.computer.height" ); + ComputerCraft.pocketTermWidth = serverConfig.get( "term_sizes.pocket_computer.width" ); + ComputerCraft.pocketTermHeight = serverConfig.get( "term_sizes.pocket_computer.height" ); + ComputerCraft.monitorWidth = serverConfig.get( "term_sizes.monitor.width" ); + ComputerCraft.monitorHeight = serverConfig.get( "term_sizes.monitor.height" ); } // Client - if(clientConfig != null) { - ComputerCraft.monitorRenderer = clientConfig.getEnum("monitor_renderer", MonitorRenderer.class); - int distance = clientConfig.get("monitor_distance"); + if( clientConfig != null ) + { + ComputerCraft.monitorRenderer = clientConfig.getEnum( "monitor_renderer", MonitorRenderer.class ); + int distance = clientConfig.get( "monitor_distance" ); ComputerCraft.monitorDistanceSq = distance * distance; } } - private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE); + private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo( CaseFormat.UPPER_UNDERSCORE ); - private static TurtleAction getAction(String value) { - try { - return TurtleAction.valueOf(converter.convert(value)); + private static TurtleAction getAction( String value ) + { + try + { + return TurtleAction.valueOf( converter.convert( value ) ); } - catch(IllegalArgumentException e) { + catch( IllegalArgumentException e ) + { return null; } } diff --git a/src/main/java/dan200/computercraft/shared/util/DefaultInventory.java b/src/main/java/dan200/computercraft/shared/util/DefaultInventory.java index 680a173f9..857fafd34 100644 --- a/src/main/java/dan200/computercraft/shared/util/DefaultInventory.java +++ b/src/main/java/dan200/computercraft/shared/util/DefaultInventory.java @@ -6,28 +6,33 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; -public interface DefaultInventory extends Inventory { +import javax.annotation.Nonnull; + +public interface DefaultInventory extends Inventory +{ @Override - default int getMaxCountPerStack() { + default int getMaxCountPerStack() + { return 64; } @Override - default void onOpen(@Nonnull PlayerEntity player) { + default void onOpen( @Nonnull PlayerEntity player ) + { } @Override - default void onClose(@Nonnull PlayerEntity player) { + default void onClose( @Nonnull PlayerEntity player ) + { } @Override - default boolean isValid(int slot, @Nonnull ItemStack stack) { + default boolean isValid( int slot, @Nonnull ItemStack stack ) + { return true; } } diff --git a/src/main/java/dan200/computercraft/shared/util/DefaultSidedInventory.java b/src/main/java/dan200/computercraft/shared/util/DefaultSidedInventory.java index fca4ee022..f2b234516 100644 --- a/src/main/java/dan200/computercraft/shared/util/DefaultSidedInventory.java +++ b/src/main/java/dan200/computercraft/shared/util/DefaultSidedInventory.java @@ -6,21 +6,24 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import net.minecraft.inventory.SidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Direction; -public interface DefaultSidedInventory extends DefaultInventory, SidedInventory { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface DefaultSidedInventory extends DefaultInventory, SidedInventory +{ @Override - default boolean canInsert(int slot, @Nonnull ItemStack stack, @Nullable Direction side) { - return this.isValid(slot, stack); + default boolean canInsert( int slot, @Nonnull ItemStack stack, @Nullable Direction side ) + { + return this.isValid( slot, stack ); } @Override - default boolean canExtract(int slot, @Nonnull ItemStack stack, @Nonnull Direction side) { + default boolean canExtract( int slot, @Nonnull ItemStack stack, @Nonnull Direction side ) + { return true; } } diff --git a/src/main/java/dan200/computercraft/shared/util/DirectionUtil.java b/src/main/java/dan200/computercraft/shared/util/DirectionUtil.java index 9e1c7cc1a..9f6cb01a9 100644 --- a/src/main/java/dan200/computercraft/shared/util/DirectionUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/DirectionUtil.java @@ -7,45 +7,54 @@ package dan200.computercraft.shared.util; import dan200.computercraft.core.computer.ComputerSide; - import net.minecraft.util.math.Direction; -public final class DirectionUtil { +public final class DirectionUtil +{ public static final Direction[] FACINGS = Direction.values(); private DirectionUtil() {} - public static ComputerSide toLocal(Direction front, Direction dir) { - if (front.getAxis() == Direction.Axis.Y) { + public static ComputerSide toLocal( Direction front, Direction dir ) + { + if( front.getAxis() == Direction.Axis.Y ) + { front = Direction.NORTH; } - if (dir == front) { + if( dir == front ) + { return ComputerSide.FRONT; } - if (dir == front.getOpposite()) { + if( dir == front.getOpposite() ) + { return ComputerSide.BACK; } - if (dir == front.rotateYCounterclockwise()) { + if( dir == front.rotateYCounterclockwise() ) + { return ComputerSide.LEFT; } - if (dir == front.rotateYClockwise()) { + if( dir == front.rotateYClockwise() ) + { return ComputerSide.RIGHT; } - if (dir == Direction.UP) { + if( dir == Direction.UP ) + { return ComputerSide.TOP; } return ComputerSide.BOTTOM; } - public static float toPitchAngle(Direction dir) { - switch (dir) { - case DOWN: - return 90.0f; - case UP: - return 270.0f; - default: - return 0.0f; + public static float toPitchAngle( Direction dir ) + { + switch( dir ) + { + case DOWN: + return 90.0f; + case UP: + return 270.0f; + default: + return 0.0f; } } } diff --git a/src/main/java/dan200/computercraft/shared/util/DropConsumer.java b/src/main/java/dan200/computercraft/shared/util/DropConsumer.java index f75be1e3f..43bb89d84 100644 --- a/src/main/java/dan200/computercraft/shared/util/DropConsumer.java +++ b/src/main/java/dan200/computercraft/shared/util/DropConsumer.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.util; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; import net.minecraft.item.ItemStack; @@ -18,34 +13,45 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.world.World; -public final class DropConsumer { +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public final class DropConsumer +{ private static Function dropConsumer; private static List remainingDrops; private static WeakReference dropWorld; private static BlockPos dropPos; private static Box dropBounds; private static WeakReference dropEntity; - private DropConsumer() { + + private DropConsumer() + { } - public static void set(Entity entity, Function consumer) { + public static void set( Entity entity, Function consumer ) + { dropConsumer = consumer; remainingDrops = new ArrayList<>(); - dropEntity = new WeakReference<>(entity); - dropWorld = new WeakReference<>(entity.world); + dropEntity = new WeakReference<>( entity ); + dropWorld = new WeakReference<>( entity.world ); dropPos = null; - dropBounds = new Box(entity.getBlockPos()).expand(2, 2, 2); + dropBounds = new Box( entity.getBlockPos() ).expand( 2, 2, 2 ); } - public static void set(World world, BlockPos pos, Function consumer) { + public static void set( World world, BlockPos pos, Function consumer ) + { dropConsumer = consumer; - remainingDrops = new ArrayList<>(2); + remainingDrops = new ArrayList<>( 2 ); dropEntity = null; - dropWorld = new WeakReference<>(world); - dropBounds = new Box(pos).expand(2, 2, 2); + dropWorld = new WeakReference<>( world ); + dropBounds = new Box( pos ).expand( 2, 2, 2 ); } - public static List clear() { + public static List clear() + { List remainingStacks = remainingDrops; dropConsumer = null; @@ -57,33 +63,41 @@ public final class DropConsumer { return remainingStacks; } - public static boolean onHarvestDrops(World world, BlockPos pos, ItemStack stack) { - if (dropWorld != null && dropWorld.get() == world && dropPos != null && dropPos.equals(pos)) { - handleDrops(stack); + public static boolean onHarvestDrops( World world, BlockPos pos, ItemStack stack ) + { + if( dropWorld != null && dropWorld.get() == world && dropPos != null && dropPos.equals( pos ) ) + { + handleDrops( stack ); return true; } return false; } - private static void handleDrops(ItemStack stack) { - ItemStack remaining = dropConsumer.apply(stack); - if (!remaining.isEmpty()) { - remainingDrops.add(remaining); + private static void handleDrops( ItemStack stack ) + { + ItemStack remaining = dropConsumer.apply( stack ); + if( !remaining.isEmpty() ) + { + remainingDrops.add( remaining ); } } - public static boolean onEntitySpawn(Entity entity) { + public static boolean onEntitySpawn( Entity entity ) + { // Capture any nearby item spawns - if (dropWorld != null && dropWorld.get() == entity.getEntityWorld() && entity instanceof ItemEntity && dropBounds.contains(entity.getPos())) { - handleDrops(((ItemEntity) entity).getStack()); + if( dropWorld != null && dropWorld.get() == entity.getEntityWorld() && entity instanceof ItemEntity && dropBounds.contains( entity.getPos() ) ) + { + handleDrops( ((ItemEntity) entity).getStack() ); return true; } return false; } - public static boolean onLivingDrops(Entity entity, ItemStack stack) { - if (dropEntity != null && entity == dropEntity.get()) { - handleDrops(stack); + public static boolean onLivingDrops( Entity entity, ItemStack stack ) + { + if( dropEntity != null && entity == dropEntity.get() ) + { + handleDrops( stack ); return true; } return false; diff --git a/src/main/java/dan200/computercraft/shared/util/FakeNetHandler.java b/src/main/java/dan200/computercraft/shared/util/FakeNetHandler.java index 1a8365ce6..3be2298bd 100644 --- a/src/main/java/dan200/computercraft/shared/util/FakeNetHandler.java +++ b/src/main/java/dan200/computercraft/shared/util/FakeNetHandler.java @@ -6,11 +6,6 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.crypto.Cipher; -import javax.crypto.SecretKey; - import dan200.computercraft.api.turtle.FakePlayer; import io.netty.channel.ChannelHandlerContext; import io.netty.util.concurrent.Future; @@ -24,285 +19,358 @@ import net.minecraft.network.packet.c2s.play.*; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.text.Text; -public class FakeNetHandler extends ServerPlayNetworkHandler { - public FakeNetHandler(@Nonnull FakePlayer player) { - super(player.getServerWorld() - .getServer(), new FakeNetworkManager(), player); +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.crypto.Cipher; + +public class FakeNetHandler extends ServerPlayNetworkHandler +{ + public FakeNetHandler( @Nonnull FakePlayer player ) + { + super( player.getServerWorld() + .getServer(), new FakeNetworkManager(), player ); } @Override - public void tick() { + public void tick() + { } @Override - public void disconnect(@Nonnull Text reason) { + public void disconnect( @Nonnull Text reason ) + { } @Override - public void onPlayerInput(@Nonnull PlayerInputC2SPacket packet) { + public void onPlayerInput( @Nonnull PlayerInputC2SPacket packet ) + { } @Override - public void onVehicleMove(@Nonnull VehicleMoveC2SPacket packet) { + public void onVehicleMove( @Nonnull VehicleMoveC2SPacket packet ) + { } @Override - public void onTeleportConfirm(@Nonnull TeleportConfirmC2SPacket packet) { + public void onTeleportConfirm( @Nonnull TeleportConfirmC2SPacket packet ) + { } @Override - public void onAdvancementTab(@Nonnull AdvancementTabC2SPacket packet) { + public void onAdvancementTab( @Nonnull AdvancementTabC2SPacket packet ) + { } @Override - public void onRequestCommandCompletions(@Nonnull RequestCommandCompletionsC2SPacket packet) { + public void onRequestCommandCompletions( @Nonnull RequestCommandCompletionsC2SPacket packet ) + { } @Override - public void onUpdateCommandBlock(@Nonnull UpdateCommandBlockC2SPacket packet) { + public void onUpdateCommandBlock( @Nonnull UpdateCommandBlockC2SPacket packet ) + { } @Override - public void onUpdateCommandBlockMinecart(@Nonnull UpdateCommandBlockMinecartC2SPacket packet) { + public void onUpdateCommandBlockMinecart( @Nonnull UpdateCommandBlockMinecartC2SPacket packet ) + { } @Override - public void onPickFromInventory(@Nonnull PickFromInventoryC2SPacket packet) { + public void onPickFromInventory( @Nonnull PickFromInventoryC2SPacket packet ) + { } @Override - public void onRenameItem(@Nonnull RenameItemC2SPacket packet) { + public void onRenameItem( @Nonnull RenameItemC2SPacket packet ) + { } @Override - public void onUpdateBeacon(@Nonnull UpdateBeaconC2SPacket packet) { + public void onUpdateBeacon( @Nonnull UpdateBeaconC2SPacket packet ) + { } @Override - public void onStructureBlockUpdate(@Nonnull UpdateStructureBlockC2SPacket packet) { + public void onStructureBlockUpdate( @Nonnull UpdateStructureBlockC2SPacket packet ) + { } @Override - public void onJigsawUpdate(@Nonnull UpdateJigsawC2SPacket packet) { + public void onJigsawUpdate( @Nonnull UpdateJigsawC2SPacket packet ) + { } @Override - public void onJigsawGenerating(JigsawGeneratingC2SPacket packet) { + public void onJigsawGenerating( JigsawGeneratingC2SPacket packet ) + { } @Override - public void onMerchantTradeSelect(SelectMerchantTradeC2SPacket packet) { + public void onMerchantTradeSelect( SelectMerchantTradeC2SPacket packet ) + { } @Override - public void onBookUpdate(@Nonnull BookUpdateC2SPacket packet) { + public void onBookUpdate( @Nonnull BookUpdateC2SPacket packet ) + { } @Override - public void onRecipeBookData(RecipeBookDataC2SPacket packet) { + public void onRecipeBookData( RecipeBookDataC2SPacket packet ) + { } @Override - public void onRecipeCategoryOptions(RecipeCategoryOptionsC2SPacket packet) { - super.onRecipeCategoryOptions(packet); + public void onRecipeCategoryOptions( RecipeCategoryOptionsC2SPacket packet ) + { + super.onRecipeCategoryOptions( packet ); } @Override - public void onQueryEntityNbt(@Nonnull QueryEntityNbtC2SPacket packet) { + public void onQueryEntityNbt( @Nonnull QueryEntityNbtC2SPacket packet ) + { } @Override - public void onQueryBlockNbt(@Nonnull QueryBlockNbtC2SPacket packet) { + public void onQueryBlockNbt( @Nonnull QueryBlockNbtC2SPacket packet ) + { } @Override - public void onPlayerMove(@Nonnull PlayerMoveC2SPacket packet) { + public void onPlayerMove( @Nonnull PlayerMoveC2SPacket packet ) + { } @Override - public void onPlayerAction(@Nonnull PlayerActionC2SPacket packet) { + public void onPlayerAction( @Nonnull PlayerActionC2SPacket packet ) + { } @Override - public void onPlayerInteractBlock(@Nonnull PlayerInteractBlockC2SPacket packet) { + public void onPlayerInteractBlock( @Nonnull PlayerInteractBlockC2SPacket packet ) + { } @Override - public void onPlayerInteractItem(@Nonnull PlayerInteractItemC2SPacket packet) { + public void onPlayerInteractItem( @Nonnull PlayerInteractItemC2SPacket packet ) + { } @Override - public void onSpectatorTeleport(@Nonnull SpectatorTeleportC2SPacket packet) { + public void onSpectatorTeleport( @Nonnull SpectatorTeleportC2SPacket packet ) + { } @Override - public void onResourcePackStatus(@Nonnull ResourcePackStatusC2SPacket packet) { + public void onResourcePackStatus( @Nonnull ResourcePackStatusC2SPacket packet ) + { } @Override - public void onBoatPaddleState(@Nonnull BoatPaddleStateC2SPacket packet) { + public void onBoatPaddleState( @Nonnull BoatPaddleStateC2SPacket packet ) + { } @Override - public void onDisconnected(@Nonnull Text reason) { + public void onDisconnected( @Nonnull Text reason ) + { } @Override - public void sendPacket(@Nonnull Packet packet) { + public void sendPacket( @Nonnull Packet packet ) + { } @Override - public void sendPacket(@Nonnull Packet packet, @Nullable GenericFutureListener> whenSent) { + public void sendPacket( @Nonnull Packet packet, @Nullable GenericFutureListener> whenSent ) + { } @Override - public void onUpdateSelectedSlot(@Nonnull UpdateSelectedSlotC2SPacket packet) { + public void onUpdateSelectedSlot( @Nonnull UpdateSelectedSlotC2SPacket packet ) + { } @Override - public void onGameMessage(@Nonnull ChatMessageC2SPacket packet) { + public void onGameMessage( @Nonnull ChatMessageC2SPacket packet ) + { } @Override - public void onHandSwing(@Nonnull HandSwingC2SPacket packet) { + public void onHandSwing( @Nonnull HandSwingC2SPacket packet ) + { } @Override - public void onClientCommand(@Nonnull ClientCommandC2SPacket packet) { + public void onClientCommand( @Nonnull ClientCommandC2SPacket packet ) + { } @Override - public void onPlayerInteractEntity(@Nonnull PlayerInteractEntityC2SPacket packet) { + public void onPlayerInteractEntity( @Nonnull PlayerInteractEntityC2SPacket packet ) + { } @Override - public void onClientStatus(@Nonnull ClientStatusC2SPacket packet) { + public void onClientStatus( @Nonnull ClientStatusC2SPacket packet ) + { } @Override - public void onCloseHandledScreen(CloseHandledScreenC2SPacket packet) { + public void onCloseHandledScreen( CloseHandledScreenC2SPacket packet ) + { } @Override - public void onClickSlot(ClickSlotC2SPacket packet) { + public void onClickSlot( ClickSlotC2SPacket packet ) + { } @Override - public void onCraftRequest(@Nonnull CraftRequestC2SPacket packet) { + public void onCraftRequest( @Nonnull CraftRequestC2SPacket packet ) + { } @Override - public void onButtonClick(@Nonnull ButtonClickC2SPacket packet) { + public void onButtonClick( @Nonnull ButtonClickC2SPacket packet ) + { } @Override - public void onCreativeInventoryAction(@Nonnull CreativeInventoryActionC2SPacket packet) { + public void onCreativeInventoryAction( @Nonnull CreativeInventoryActionC2SPacket packet ) + { } @Override - public void onConfirmScreenAction(ConfirmScreenActionC2SPacket packet) { + public void onConfirmScreenAction( ConfirmScreenActionC2SPacket packet ) + { } @Override - public void onSignUpdate(@Nonnull UpdateSignC2SPacket packet) { + public void onSignUpdate( @Nonnull UpdateSignC2SPacket packet ) + { } @Override - public void onKeepAlive(@Nonnull KeepAliveC2SPacket packet) { + public void onKeepAlive( @Nonnull KeepAliveC2SPacket packet ) + { } @Override - public void onPlayerAbilities(@Nonnull UpdatePlayerAbilitiesC2SPacket packet) { + public void onPlayerAbilities( @Nonnull UpdatePlayerAbilitiesC2SPacket packet ) + { } @Override - public void onClientSettings(@Nonnull ClientSettingsC2SPacket packet) { + public void onClientSettings( @Nonnull ClientSettingsC2SPacket packet ) + { } @Override - public void onCustomPayload(@Nonnull CustomPayloadC2SPacket packet) { + public void onCustomPayload( @Nonnull CustomPayloadC2SPacket packet ) + { } @Override - public void onUpdateDifficulty(@Nonnull UpdateDifficultyC2SPacket packet) { + public void onUpdateDifficulty( @Nonnull UpdateDifficultyC2SPacket packet ) + { } @Override - public void onUpdateDifficultyLock(@Nonnull UpdateDifficultyLockC2SPacket packet) { + public void onUpdateDifficultyLock( @Nonnull UpdateDifficultyLockC2SPacket packet ) + { } - private static class FakeNetworkManager extends ClientConnection { + private static class FakeNetworkManager extends ClientConnection + { private PacketListener handler; private Text closeReason; - FakeNetworkManager() { - super(NetworkSide.CLIENTBOUND); + FakeNetworkManager() + { + super( NetworkSide.CLIENTBOUND ); } @Override - public void channelActive(@Nonnull ChannelHandlerContext context) { + public void channelActive( @Nonnull ChannelHandlerContext context ) + { } @Override - public void setState(@Nonnull NetworkState state) { + public void setState( @Nonnull NetworkState state ) + { } @Override - public void channelInactive(@Nonnull ChannelHandlerContext context) { + public void channelInactive( @Nonnull ChannelHandlerContext context ) + { } @Override - public void exceptionCaught(@Nonnull ChannelHandlerContext context, @Nonnull Throwable err) { + public void exceptionCaught( @Nonnull ChannelHandlerContext context, @Nonnull Throwable err ) + { } @Override - protected void channelRead0(@Nonnull ChannelHandlerContext context, @Nonnull Packet packet) { + protected void channelRead0( @Nonnull ChannelHandlerContext context, @Nonnull Packet packet ) + { } @Override - public void setPacketListener(@Nonnull PacketListener handler) { + public void setPacketListener( @Nonnull PacketListener handler ) + { this.handler = handler; } @Override - public void send(@Nonnull Packet packet) { + public void send( @Nonnull Packet packet ) + { } @Override - public void send(@Nonnull Packet packet, @Nullable GenericFutureListener> whenSent) { + public void send( @Nonnull Packet packet, @Nullable GenericFutureListener> whenSent ) + { } @Override - public void tick() { + public void tick() + { } @Override - public void disconnect(@Nonnull Text message) { + public void disconnect( @Nonnull Text message ) + { this.closeReason = message; } @Override - public void setupEncryption(Cipher cipher, Cipher cipher2) { + public void setupEncryption( Cipher cipher, Cipher cipher2 ) + { } @Nonnull @Override - public PacketListener getPacketListener() { + public PacketListener getPacketListener() + { return this.handler; } @Nullable @Override - public Text getDisconnectReason() { + public Text getDisconnectReason() + { return this.closeReason; } @Override - public void disableAutoRead() { + public void disableAutoRead() + { } @Override - public void setCompressionThreshold(int threshold) { + public void setCompressionThreshold( int threshold ) + { } } } diff --git a/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java b/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java index 20d1dd597..62bb4ceb0 100644 --- a/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java +++ b/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java @@ -6,50 +6,56 @@ package dan200.computercraft.shared.util; -import java.util.Collections; -import java.util.function.Function; -import java.util.function.Supplier; - -import javax.annotation.Nonnull; - import net.minecraft.block.Block; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.function.Function; +import java.util.function.Supplier; + /** * A {@link BlockEntityType} whose supplier uses itself as an argument. * * @param The type of the produced tile entity. */ -public final class FixedPointTileEntityType extends BlockEntityType { +public final class FixedPointTileEntityType extends BlockEntityType +{ private final Supplier block; - private FixedPointTileEntityType(Supplier block, Supplier builder) { - super(builder, Collections.emptySet(), null); + private FixedPointTileEntityType( Supplier block, Supplier builder ) + { + super( builder, Collections.emptySet(), null ); this.block = block; } - public static FixedPointTileEntityType create(Supplier block, Function, T> builder) { - return new FixedPointSupplier<>(block, builder).factory; + public static FixedPointTileEntityType create( Supplier block, Function, T> builder ) + { + return new FixedPointSupplier<>( block, builder ).factory; } @Override - public boolean supports(@Nonnull Block block) { + public boolean supports( @Nonnull Block block ) + { return block == this.block.get(); } - private static final class FixedPointSupplier implements Supplier { + private static final class FixedPointSupplier implements Supplier + { final FixedPointTileEntityType factory; private final Function, T> builder; - private FixedPointSupplier(Supplier block, Function, T> builder) { - this.factory = new FixedPointTileEntityType<>(block, this); + private FixedPointSupplier( Supplier block, Function, T> builder ) + { + this.factory = new FixedPointTileEntityType<>( block, this ); this.builder = builder; } @Override - public T get() { - return this.builder.apply(this.factory); + public T get() + { + return this.builder.apply( this.factory ); } } } diff --git a/src/main/java/dan200/computercraft/shared/util/Holiday.java b/src/main/java/dan200/computercraft/shared/util/Holiday.java index 3cea58e7e..2b1dd385b 100644 --- a/src/main/java/dan200/computercraft/shared/util/Holiday.java +++ b/src/main/java/dan200/computercraft/shared/util/Holiday.java @@ -6,6 +6,7 @@ package dan200.computercraft.shared.util; -public enum Holiday { +public enum Holiday +{ NONE, VALENTINES, APRIL_FOOLS_DAY, HALLOWEEN, CHRISTMAS, } diff --git a/src/main/java/dan200/computercraft/shared/util/HolidayUtil.java b/src/main/java/dan200/computercraft/shared/util/HolidayUtil.java index 0e893bde1..e24ce3610 100644 --- a/src/main/java/dan200/computercraft/shared/util/HolidayUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/HolidayUtil.java @@ -8,26 +8,33 @@ package dan200.computercraft.shared.util; import java.util.Calendar; -public final class HolidayUtil { +public final class HolidayUtil +{ private HolidayUtil() {} - public static Holiday getCurrentHoliday() { - return getHoliday(Calendar.getInstance()); + public static Holiday getCurrentHoliday() + { + return getHoliday( Calendar.getInstance() ); } - private static Holiday getHoliday(Calendar calendar) { - int month = calendar.get(Calendar.MONTH); - int day = calendar.get(Calendar.DAY_OF_MONTH); - if (month == Calendar.FEBRUARY && day == 14) { + private static Holiday getHoliday( Calendar calendar ) + { + int month = calendar.get( Calendar.MONTH ); + int day = calendar.get( Calendar.DAY_OF_MONTH ); + if( month == Calendar.FEBRUARY && day == 14 ) + { return Holiday.VALENTINES; } - if (month == Calendar.APRIL && day == 1) { + if( month == Calendar.APRIL && day == 1 ) + { return Holiday.APRIL_FOOLS_DAY; } - if (month == Calendar.OCTOBER && day == 31) { + if( month == Calendar.OCTOBER && day == 31 ) + { return Holiday.HALLOWEEN; } - if (month == Calendar.DECEMBER && day >= 24 && day <= 30) { + if( month == Calendar.DECEMBER && day >= 24 && day <= 30 ) + { return Holiday.CHRISTMAS; } return Holiday.NONE; diff --git a/src/main/java/dan200/computercraft/shared/util/IDAssigner.java b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java index 0ef5db760..b50822b6c 100644 --- a/src/main/java/dan200/computercraft/shared/util/IDAssigner.java +++ b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java @@ -6,6 +6,15 @@ package dan200.computercraft.shared.util; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.fabric.mixin.WorldSavePathAccess; +import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.WorldSavePath; + import java.io.File; import java.io.Reader; import java.io.Writer; @@ -17,85 +26,95 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.fabric.mixin.WorldSavePathAccess; -import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.WorldSavePath; - -public final class IDAssigner { - private static final WorldSavePath FOLDER = WorldSavePathAccess.createWorldSavePath(ComputerCraft.MOD_ID); +public final class IDAssigner +{ + private static final WorldSavePath FOLDER = WorldSavePathAccess.createWorldSavePath( ComputerCraft.MOD_ID ); private static final Gson GSON = new GsonBuilder().setPrettyPrinting() - .create(); + .create(); private static final Type ID_TOKEN = new TypeToken>() {}.getType(); private static Map ids; private static WeakReference server; private static Path idFile; - private IDAssigner() { + + private IDAssigner() + { } - public static synchronized int getNextId(String kind) { + public static synchronized int getNextId( String kind ) + { MinecraftServer currentServer = getCachedServer(); - if (currentServer == null) { + if( currentServer == null ) + { // The server has changed, refetch our ID map - if (GameInstanceUtils.getServer() != null) { - server = new WeakReference<>(GameInstanceUtils.getServer()); + if( GameInstanceUtils.getServer() != null ) + { + server = new WeakReference<>( GameInstanceUtils.getServer() ); File dir = getDir(); dir.mkdirs(); // Load our ID file from disk - idFile = new File(dir, "ids.json").toPath(); - if (Files.isRegularFile(idFile)) { - try (Reader reader = Files.newBufferedReader(idFile, StandardCharsets.UTF_8)) { - ids = GSON.fromJson(reader, ID_TOKEN); - } catch (Exception e) { - ComputerCraft.log.error("Cannot load id file '" + idFile + "'", e); + idFile = new File( dir, "ids.json" ).toPath(); + if( Files.isRegularFile( idFile ) ) + { + try( Reader reader = Files.newBufferedReader( idFile, StandardCharsets.UTF_8 ) ) + { + ids = GSON.fromJson( reader, ID_TOKEN ); + } + catch( Exception e ) + { + ComputerCraft.log.error( "Cannot load id file '" + idFile + "'", e ); ids = new HashMap<>(); } - } else { + } + else + { ids = new HashMap<>(); } } } - Integer existing = ids.get(kind); + Integer existing = ids.get( kind ); int next = existing == null ? 0 : existing + 1; - ids.put(kind, next); + ids.put( kind, next ); // We've changed the ID file, so save it back again. - try (Writer writer = Files.newBufferedWriter(idFile, StandardCharsets.UTF_8)) { - GSON.toJson(ids, writer); - } catch (Exception e) { - ComputerCraft.log.error("Cannot update ID file '" + idFile + "'", e); + try( Writer writer = Files.newBufferedWriter( idFile, StandardCharsets.UTF_8 ) ) + { + GSON.toJson( ids, writer ); + } + catch( Exception e ) + { + ComputerCraft.log.error( "Cannot update ID file '" + idFile + "'", e ); } return next; } - private static MinecraftServer getCachedServer() { - if (server == null) { + private static MinecraftServer getCachedServer() + { + if( server == null ) + { return null; } MinecraftServer currentServer = server.get(); - if (currentServer == null) { + if( currentServer == null ) + { return null; } - if (currentServer != GameInstanceUtils.getServer()) { + if( currentServer != GameInstanceUtils.getServer() ) + { return null; } return currentServer; } - public static File getDir() { + public static File getDir() + { return GameInstanceUtils.getServer() - .getSavePath(FOLDER) - .toFile(); + .getSavePath( FOLDER ) + .toFile(); } } diff --git a/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java b/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java index 2ed3f5e8f..2958e421f 100644 --- a/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java +++ b/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java @@ -6,10 +6,7 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; - import com.google.gson.JsonObject; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; @@ -21,68 +18,82 @@ import net.minecraft.util.JsonHelper; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -public final class ImpostorRecipe extends ShapedRecipe { - public static final RecipeSerializer SERIALIZER = new RecipeSerializer() { +import javax.annotation.Nonnull; + +public final class ImpostorRecipe extends ShapedRecipe +{ + public static final RecipeSerializer SERIALIZER = new RecipeSerializer() + { @Override - public ImpostorRecipe read(@Nonnull Identifier identifier, @Nonnull JsonObject json) { - String group = JsonHelper.getString(json, "group", ""); - ShapedRecipe recipe = RecipeSerializer.SHAPED.read(identifier, json); - ItemStack result = ShapedRecipe.getItemStack(JsonHelper.getObject(json, "result")); - return new ImpostorRecipe(identifier, group, recipe.getWidth(), recipe.getHeight(), recipe.getPreviewInputs(), result); + public ImpostorRecipe read( @Nonnull Identifier identifier, @Nonnull JsonObject json ) + { + String group = JsonHelper.getString( json, "group", "" ); + ShapedRecipe recipe = RecipeSerializer.SHAPED.read( identifier, json ); + ItemStack result = ShapedRecipe.getItemStack( JsonHelper.getObject( json, "result" ) ); + return new ImpostorRecipe( identifier, group, recipe.getWidth(), recipe.getHeight(), recipe.getPreviewInputs(), result ); } @Override - public ImpostorRecipe read(@Nonnull Identifier identifier, @Nonnull PacketByteBuf buf) { + public ImpostorRecipe read( @Nonnull Identifier identifier, @Nonnull PacketByteBuf buf ) + { int width = buf.readVarInt(); int height = buf.readVarInt(); - String group = buf.readString(Short.MAX_VALUE); - DefaultedList items = DefaultedList.ofSize(width * height, Ingredient.EMPTY); - for (int k = 0; k < items.size(); ++k) { - items.set(k, Ingredient.fromPacket(buf)); + String group = buf.readString( Short.MAX_VALUE ); + DefaultedList items = DefaultedList.ofSize( width * height, Ingredient.EMPTY ); + for( int k = 0; k < items.size(); ++k ) + { + items.set( k, Ingredient.fromPacket( buf ) ); } ItemStack result = buf.readItemStack(); - return new ImpostorRecipe(identifier, group, width, height, items, result); + return new ImpostorRecipe( identifier, group, width, height, items, result ); } @Override - public void write(@Nonnull PacketByteBuf buf, @Nonnull ImpostorRecipe recipe) { - buf.writeVarInt(recipe.getWidth()); - buf.writeVarInt(recipe.getHeight()); - buf.writeString(recipe.getGroup()); - for (Ingredient ingredient : recipe.getPreviewInputs()) { - ingredient.write(buf); + public void write( @Nonnull PacketByteBuf buf, @Nonnull ImpostorRecipe recipe ) + { + buf.writeVarInt( recipe.getWidth() ); + buf.writeVarInt( recipe.getHeight() ); + buf.writeString( recipe.getGroup() ); + for( Ingredient ingredient : recipe.getPreviewInputs() ) + { + ingredient.write( buf ); } - buf.writeItemStack(recipe.getOutput()); + buf.writeItemStack( recipe.getOutput() ); } }; private final String group; - private ImpostorRecipe(@Nonnull Identifier id, @Nonnull String group, int width, int height, DefaultedList ingredients, - @Nonnull ItemStack result) { - super(id, group, width, height, ingredients, result); + private ImpostorRecipe( @Nonnull Identifier id, @Nonnull String group, int width, int height, DefaultedList ingredients, + @Nonnull ItemStack result ) + { + super( id, group, width, height, ingredients, result ); this.group = group; } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } @Nonnull @Override - public String getGroup() { + public String getGroup() + { return this.group; } @Override - public boolean matches(@Nonnull CraftingInventory inv, @Nonnull World world) { + public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) + { return false; } @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inventory) { + public ItemStack craft( @Nonnull CraftingInventory inventory ) + { return ItemStack.EMPTY; } } diff --git a/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java b/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java index 4ebb39cbc..b84e4bfe4 100644 --- a/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java +++ b/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java @@ -6,12 +6,9 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; - import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; - import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; @@ -24,30 +21,40 @@ import net.minecraft.util.JsonHelper; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -public final class ImpostorShapelessRecipe extends ShapelessRecipe { - public static final RecipeSerializer SERIALIZER = new RecipeSerializer() { +import javax.annotation.Nonnull; + +public final class ImpostorShapelessRecipe extends ShapelessRecipe +{ + public static final RecipeSerializer SERIALIZER = new RecipeSerializer() + { @Override - public ImpostorShapelessRecipe read(@Nonnull Identifier id, @Nonnull JsonObject json) { - String s = JsonHelper.getString(json, "group", ""); - DefaultedList ingredients = this.readIngredients(JsonHelper.getArray(json, "ingredients")); + public ImpostorShapelessRecipe read( @Nonnull Identifier id, @Nonnull JsonObject json ) + { + String s = JsonHelper.getString( json, "group", "" ); + DefaultedList ingredients = this.readIngredients( JsonHelper.getArray( json, "ingredients" ) ); - if (ingredients.isEmpty()) { - throw new JsonParseException("No ingredients for shapeless recipe"); + if( ingredients.isEmpty() ) + { + throw new JsonParseException( "No ingredients for shapeless recipe" ); } - if (ingredients.size() > 9) { - throw new JsonParseException("Too many ingredients for shapeless recipe the max is 9"); + if( ingredients.size() > 9 ) + { + throw new JsonParseException( "Too many ingredients for shapeless recipe the max is 9" ); } - ItemStack itemstack = ShapedRecipe.getItemStack(JsonHelper.getObject(json, "result")); - return new ImpostorShapelessRecipe(id, s, itemstack, ingredients); + ItemStack itemstack = ShapedRecipe.getItemStack( JsonHelper.getObject( json, "result" ) ); + return new ImpostorShapelessRecipe( id, s, itemstack, ingredients ); } - private DefaultedList readIngredients(JsonArray arrays) { + private DefaultedList readIngredients( JsonArray arrays ) + { DefaultedList items = DefaultedList.of(); - for (int i = 0; i < arrays.size(); ++i) { - Ingredient ingredient = Ingredient.fromJson(arrays.get(i)); - if (!ingredient.isEmpty()) { - items.add(ingredient); + for( int i = 0; i < arrays.size(); ++i ) + { + Ingredient ingredient = Ingredient.fromJson( arrays.get( i ) ); + if( !ingredient.isEmpty() ) + { + items.add( ingredient ); } } @@ -55,58 +62,67 @@ public final class ImpostorShapelessRecipe extends ShapelessRecipe { } @Override - public ImpostorShapelessRecipe read(@Nonnull Identifier id, PacketByteBuf buffer) { - String s = buffer.readString(32767); + public ImpostorShapelessRecipe read( @Nonnull Identifier id, PacketByteBuf buffer ) + { + String s = buffer.readString( 32767 ); int i = buffer.readVarInt(); - DefaultedList items = DefaultedList.ofSize(i, Ingredient.EMPTY); + DefaultedList items = DefaultedList.ofSize( i, Ingredient.EMPTY ); - for (int j = 0; j < items.size(); j++) { - items.set(j, Ingredient.fromPacket(buffer)); + for( int j = 0; j < items.size(); j++ ) + { + items.set( j, Ingredient.fromPacket( buffer ) ); } ItemStack result = buffer.readItemStack(); - return new ImpostorShapelessRecipe(id, s, result, items); + return new ImpostorShapelessRecipe( id, s, result, items ); } @Override - public void write(@Nonnull PacketByteBuf buffer, @Nonnull ImpostorShapelessRecipe recipe) { - buffer.writeString(recipe.getGroup()); - buffer.writeVarInt(recipe.getPreviewInputs() - .size()); + public void write( @Nonnull PacketByteBuf buffer, @Nonnull ImpostorShapelessRecipe recipe ) + { + buffer.writeString( recipe.getGroup() ); + buffer.writeVarInt( recipe.getPreviewInputs() + .size() ); - for (Ingredient ingredient : recipe.getPreviewInputs()) { - ingredient.write(buffer); + for( Ingredient ingredient : recipe.getPreviewInputs() ) + { + ingredient.write( buffer ); } - buffer.writeItemStack(recipe.getOutput()); + buffer.writeItemStack( recipe.getOutput() ); } }; private final String group; - private ImpostorShapelessRecipe(@Nonnull Identifier id, @Nonnull String group, @Nonnull ItemStack result, DefaultedList ingredients) { - super(id, group, result, ingredients); + private ImpostorShapelessRecipe( @Nonnull Identifier id, @Nonnull String group, @Nonnull ItemStack result, DefaultedList ingredients ) + { + super( id, group, result, ingredients ); this.group = group; } @Nonnull @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() + { return SERIALIZER; } @Nonnull @Override - public String getGroup() { + public String getGroup() + { return this.group; } @Override - public boolean matches(@Nonnull CraftingInventory inv, @Nonnull World world) { + public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) + { return false; } @Nonnull @Override - public ItemStack craft(@Nonnull CraftingInventory inventory) { + public ItemStack craft( @Nonnull CraftingInventory inventory ) + { return ItemStack.EMPTY; } } diff --git a/src/main/java/dan200/computercraft/shared/util/InventoryDelegate.java b/src/main/java/dan200/computercraft/shared/util/InventoryDelegate.java index 935755ca5..f66bb98d4 100644 --- a/src/main/java/dan200/computercraft/shared/util/InventoryDelegate.java +++ b/src/main/java/dan200/computercraft/shared/util/InventoryDelegate.java @@ -6,15 +6,14 @@ package dan200.computercraft.shared.util; -import java.util.Set; - -import javax.annotation.Nonnull; - import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import javax.annotation.Nonnull; +import java.util.Set; + /** * Provides a delegate over inventories. * @@ -22,84 +21,100 @@ import net.minecraft.item.ItemStack; * inventories which change their backing store. */ @FunctionalInterface -public interface InventoryDelegate extends Inventory { +public interface InventoryDelegate extends Inventory +{ @Override - default int size() { + default int size() + { return this.getInventory().size(); } Inventory getInventory(); @Override - default boolean isEmpty() { + default boolean isEmpty() + { return this.getInventory().isEmpty(); } @Nonnull @Override - default ItemStack getStack(int slot) { - return this.getInventory().getStack(slot); + default ItemStack getStack( int slot ) + { + return this.getInventory().getStack( slot ); } @Nonnull @Override - default ItemStack removeStack(int slot, int count) { - return this.getInventory().removeStack(slot, count); + default ItemStack removeStack( int slot, int count ) + { + return this.getInventory().removeStack( slot, count ); } @Nonnull @Override - default ItemStack removeStack(int slot) { - return this.getInventory().removeStack(slot); + default ItemStack removeStack( int slot ) + { + return this.getInventory().removeStack( slot ); } @Override - default void setStack(int slot, @Nonnull ItemStack stack) { - this.getInventory().setStack(slot, stack); + default void setStack( int slot, @Nonnull ItemStack stack ) + { + this.getInventory().setStack( slot, stack ); } @Override - default int getMaxCountPerStack() { + default int getMaxCountPerStack() + { return this.getInventory().getMaxCountPerStack(); } @Override - default void markDirty() { + default void markDirty() + { this.getInventory().markDirty(); } @Override - default boolean canPlayerUse(@Nonnull PlayerEntity player) { - return this.getInventory().canPlayerUse(player); + default boolean canPlayerUse( @Nonnull PlayerEntity player ) + { + return this.getInventory().canPlayerUse( player ); } @Override - default void onOpen(@Nonnull PlayerEntity player) { - this.getInventory().onOpen(player); + default void onOpen( @Nonnull PlayerEntity player ) + { + this.getInventory().onOpen( player ); } @Override - default void onClose(@Nonnull PlayerEntity player) { - this.getInventory().onClose(player); + default void onClose( @Nonnull PlayerEntity player ) + { + this.getInventory().onClose( player ); } @Override - default boolean isValid(int slot, @Nonnull ItemStack stack) { - return this.getInventory().isValid(slot, stack); + default boolean isValid( int slot, @Nonnull ItemStack stack ) + { + return this.getInventory().isValid( slot, stack ); } @Override - default int count(@Nonnull Item stack) { - return this.getInventory().count(stack); + default int count( @Nonnull Item stack ) + { + return this.getInventory().count( stack ); } @Override - default boolean containsAny(@Nonnull Set set) { - return this.getInventory().containsAny(set); + default boolean containsAny( @Nonnull Set set ) + { + return this.getInventory().containsAny( set ); } @Override - default void clear() { + default void clear() + { this.getInventory().clear(); } } diff --git a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java index 9eac0209e..e7bf6f8d0 100644 --- a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java @@ -6,16 +6,12 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.ChestBlock; import net.minecraft.block.InventoryProvider; -import net.minecraft.block.entity.ChestBlockEntity; -import org.apache.commons.lang3.tuple.Pair; - import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.ChestBlockEntity; import net.minecraft.entity.Entity; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; @@ -23,64 +19,79 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import org.apache.commons.lang3.tuple.Pair; -public final class InventoryUtil { +import javax.annotation.Nonnull; + +public final class InventoryUtil +{ private InventoryUtil() {} // Methods for comparing things: - public static boolean areItemsStackable(@Nonnull ItemStack a, @Nonnull ItemStack b) { - return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual(a, b)); + public static boolean areItemsStackable( @Nonnull ItemStack a, @Nonnull ItemStack b ) + { + return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual( a, b )); } // Methods for finding inventories: - public static Inventory getInventory(World world, BlockPos pos, Direction side) { + public static Inventory getInventory( World world, BlockPos pos, Direction side ) + { // Look for tile with inventory int y = pos.getY(); - if (y >= 0 && y < world.getHeight()) { + if( y >= 0 && y < world.getHeight() ) + { // Check if block is InventoryProvider - BlockState blockState = world.getBlockState(pos); + BlockState blockState = world.getBlockState( pos ); Block block = blockState.getBlock(); - if (block instanceof InventoryProvider) { - return ((InventoryProvider)block).getInventory(blockState, world, pos); + if( block instanceof InventoryProvider ) + { + return ((InventoryProvider) block).getInventory( blockState, world, pos ); } // Check if block is BlockEntity w/ Inventory - if (block.hasBlockEntity()) { - BlockEntity tileEntity = world.getBlockEntity(pos); + if( block.hasBlockEntity() ) + { + BlockEntity tileEntity = world.getBlockEntity( pos ); - Inventory inventory = getInventory(tileEntity); - if (inventory != null) { + Inventory inventory = getInventory( tileEntity ); + if( inventory != null ) + { return inventory; } } } // Look for entity with inventory - Vec3d vecStart = new Vec3d(pos.getX() + 0.5 + 0.6 * side.getOffsetX(), - pos.getY() + 0.5 + 0.6 * side.getOffsetY(), - pos.getZ() + 0.5 + 0.6 * side.getOffsetZ()); + Vec3d vecStart = new Vec3d( pos.getX() + 0.5 + 0.6 * side.getOffsetX(), + pos.getY() + 0.5 + 0.6 * side.getOffsetY(), + pos.getZ() + 0.5 + 0.6 * side.getOffsetZ() ); Direction dir = side.getOpposite(); - Vec3d vecDir = new Vec3d(dir.getOffsetX(), dir.getOffsetY(), dir.getOffsetZ()); - Pair hit = WorldUtil.rayTraceEntities(world, vecStart, vecDir, 1.1); - if (hit != null) { + Vec3d vecDir = new Vec3d( dir.getOffsetX(), dir.getOffsetY(), dir.getOffsetZ() ); + Pair hit = WorldUtil.rayTraceEntities( world, vecStart, vecDir, 1.1 ); + if( hit != null ) + { Entity entity = hit.getKey(); - if (entity instanceof Inventory) { + if( entity instanceof Inventory ) + { return (Inventory) entity; } } return null; } - public static Inventory getInventory(BlockEntity tileEntity) { + public static Inventory getInventory( BlockEntity tileEntity ) + { World world = tileEntity.getWorld(); BlockPos pos = tileEntity.getPos(); - BlockState blockState = world.getBlockState(pos); + BlockState blockState = world.getBlockState( pos ); Block block = blockState.getBlock(); - if (tileEntity instanceof Inventory) { - Inventory inventory = (Inventory)tileEntity; - if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) { - return ChestBlock.getInventory((ChestBlock) block, blockState, world, pos, true); + if( tileEntity instanceof Inventory ) + { + Inventory inventory = (Inventory) tileEntity; + if( inventory instanceof ChestBlockEntity && block instanceof ChestBlock ) + { + return ChestBlock.getInventory( (ChestBlock) block, blockState, world, pos, true ); } return inventory; } @@ -89,69 +100,84 @@ public final class InventoryUtil { } @Nonnull - public static ItemStack storeItems(@Nonnull ItemStack itemstack, ItemStorage inventory, int begin) { - return storeItems(itemstack, inventory, 0, inventory.size(), begin); + public static ItemStack storeItems( @Nonnull ItemStack itemstack, ItemStorage inventory, int begin ) + { + return storeItems( itemstack, inventory, 0, inventory.size(), begin ); } // Methods for placing into inventories: @Nonnull - public static ItemStack storeItems(@Nonnull ItemStack stack, ItemStorage inventory, int start, int range, int begin) { - if (stack.isEmpty()) { + public static ItemStack storeItems( @Nonnull ItemStack stack, ItemStorage inventory, int start, int range, int begin ) + { + if( stack.isEmpty() ) + { return ItemStack.EMPTY; } // Inspect the slots in order and try to find empty or stackable slots ItemStack remainder = stack.copy(); - for (int i = 0; i < range; i++) { + for( int i = 0; i < range; i++ ) + { int slot = start + (i + begin - start) % range; - if (remainder.isEmpty()) { + if( remainder.isEmpty() ) + { break; } - remainder = inventory.store(slot, remainder, false); + remainder = inventory.store( slot, remainder, false ); } - return areItemsEqual(stack, remainder) ? stack : remainder; + return areItemsEqual( stack, remainder ) ? stack : remainder; } - public static boolean areItemsEqual(@Nonnull ItemStack a, @Nonnull ItemStack b) { - return a == b || ItemStack.areEqual(a, b); + public static boolean areItemsEqual( @Nonnull ItemStack a, @Nonnull ItemStack b ) + { + return a == b || ItemStack.areEqual( a, b ); } @Nonnull - public static ItemStack storeItems(@Nonnull ItemStack itemstack, ItemStorage inventory) { - return storeItems(itemstack, inventory, 0, inventory.size(), 0); + public static ItemStack storeItems( @Nonnull ItemStack itemstack, ItemStorage inventory ) + { + return storeItems( itemstack, inventory, 0, inventory.size(), 0 ); } // Methods for taking out of inventories @Nonnull - public static ItemStack takeItems(int count, ItemStorage inventory, int begin) { - return takeItems(count, inventory, 0, inventory.size(), begin); + public static ItemStack takeItems( int count, ItemStorage inventory, int begin ) + { + return takeItems( count, inventory, 0, inventory.size(), begin ); } @Nonnull - public static ItemStack takeItems(int count, ItemStorage inventory, int start, int range, int begin) { + public static ItemStack takeItems( int count, ItemStorage inventory, int start, int range, int begin ) + { ItemStack partialStack = ItemStack.EMPTY; - for (int i = 0; i < range; i++) { + for( int i = 0; i < range; i++ ) + { int slot = start + (i + begin - start) % range; - if (count <= 0) { + if( count <= 0 ) + { break; } // If this doesn't slot, abort. - ItemStack extracted = inventory.take(slot, count, partialStack, false); - if (extracted.isEmpty()) { + ItemStack extracted = inventory.take( slot, count, partialStack, false ); + if( extracted.isEmpty() ) + { continue; } count -= extracted.getCount(); - if (partialStack.isEmpty()) { + if( partialStack.isEmpty() ) + { // If we've extracted for this first time, then limit the count to the maximum stack size. partialStack = extracted; - count = Math.min(count, extracted.getMaxCount()); - } else { - partialStack.increment(extracted.getCount()); + count = Math.min( count, extracted.getMaxCount() ); + } + else + { + partialStack.increment( extracted.getCount() ); } } @@ -159,7 +185,8 @@ public final class InventoryUtil { } @Nonnull - public static ItemStack takeItems(int count, ItemStorage inventory) { - return takeItems(count, inventory, 0, inventory.size(), 0); + public static ItemStack takeItems( int count, ItemStorage inventory ) + { + return takeItems( count, inventory, 0, inventory.size(), 0 ); } } diff --git a/src/main/java/dan200/computercraft/shared/util/IoUtil.java b/src/main/java/dan200/computercraft/shared/util/IoUtil.java index 30a89a935..eb915596b 100644 --- a/src/main/java/dan200/computercraft/shared/util/IoUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/IoUtil.java @@ -6,20 +6,25 @@ package dan200.computercraft.shared.util; +import javax.annotation.Nullable; import java.io.Closeable; import java.io.IOException; -import javax.annotation.Nullable; - -public final class IoUtil { +public final class IoUtil +{ private IoUtil() {} - public static void closeQuietly(@Nullable Closeable closeable) { - try { - if (closeable != null) { + public static void closeQuietly( @Nullable Closeable closeable ) + { + try + { + if( closeable != null ) + { closeable.close(); } - } catch (IOException ignored) { + } + catch( IOException ignored ) + { } } } diff --git a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java index b5cbd096a..f0787f61d 100644 --- a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java +++ b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java @@ -5,242 +5,299 @@ */ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; - import net.minecraft.inventory.Inventory; import net.minecraft.inventory.SidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Direction; +import javax.annotation.Nonnull; + /** * The most cutesy alternative of {@code IItemHandler} the world has ever seen. */ -public interface ItemStorage { - static ItemStorage wrap(Inventory inventory) { - return new InventoryWrapper(inventory); +public interface ItemStorage +{ + static ItemStorage wrap( Inventory inventory ) + { + return new InventoryWrapper( inventory ); } - static ItemStorage wrap(@Nonnull SidedInventory inventory, @Nonnull Direction facing) { - return new SidedInventoryWrapper(inventory, facing); + static ItemStorage wrap( @Nonnull SidedInventory inventory, @Nonnull Direction facing ) + { + return new SidedInventoryWrapper( inventory, facing ); } - static ItemStorage wrap(@Nonnull Inventory inventory, @Nonnull Direction facing) { - return inventory instanceof SidedInventory ? new SidedInventoryWrapper((SidedInventory) inventory, facing) : new InventoryWrapper(inventory); + static ItemStorage wrap( @Nonnull Inventory inventory, @Nonnull Direction facing ) + { + return inventory instanceof SidedInventory ? new SidedInventoryWrapper( (SidedInventory) inventory, facing ) : new InventoryWrapper( inventory ); } - static boolean areStackable(@Nonnull ItemStack a, @Nonnull ItemStack b) { - return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual(a, b)); + static boolean areStackable( @Nonnull ItemStack a, @Nonnull ItemStack b ) + { + return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual( a, b )); } int size(); @Nonnull - ItemStack getStack(int slot); + ItemStack getStack( int slot ); @Nonnull - ItemStack take(int slot, int limit, @Nonnull ItemStack filter, boolean simulate); + ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ); @Nonnull - ItemStack store(int slot, @Nonnull ItemStack stack, boolean simulate); + ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ); - default ItemStorage view(int start, int size) { - return new View(this, start, size); + default ItemStorage view( int start, int size ) + { + return new View( this, start, size ); } - class InventoryWrapper implements ItemStorage { + class InventoryWrapper implements ItemStorage + { private final Inventory inventory; - InventoryWrapper(Inventory inventory) { + InventoryWrapper( Inventory inventory ) + { this.inventory = inventory; } @Override - public int size() { + public int size() + { return this.inventory.size(); } @Override @Nonnull - public ItemStack getStack(int slot) { - return this.inventory.getStack(slot); + public ItemStack getStack( int slot ) + { + return this.inventory.getStack( slot ); } @Override @Nonnull - public ItemStack take(int slot, int limit, @Nonnull ItemStack filter, boolean simulate) { - ItemStack existing = this.inventory.getStack(slot); - if (existing.isEmpty() || !this.canExtract(slot, existing) || (!filter.isEmpty() && !areStackable(existing, filter))) { + public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ) + { + ItemStack existing = this.inventory.getStack( slot ); + if( existing.isEmpty() || !this.canExtract( slot, existing ) || (!filter.isEmpty() && !areStackable( existing, filter )) ) + { return ItemStack.EMPTY; } - if (simulate) { + if( simulate ) + { existing = existing.copy(); - if (existing.getCount() > limit) { - existing.setCount(limit); + if( existing.getCount() > limit ) + { + existing.setCount( limit ); } return existing; - } else if (existing.getCount() < limit) { - this.setAndDirty(slot, ItemStack.EMPTY); + } + else if( existing.getCount() < limit ) + { + this.setAndDirty( slot, ItemStack.EMPTY ); return existing; - } else { - ItemStack result = existing.split(limit); - this.setAndDirty(slot, existing); + } + else + { + ItemStack result = existing.split( limit ); + this.setAndDirty( slot, existing ); return result; } } - protected boolean canExtract(int slot, ItemStack stack) { + protected boolean canExtract( int slot, ItemStack stack ) + { return true; } - private void setAndDirty(int slot, @Nonnull ItemStack stack) { - this.inventory.setStack(slot, stack); + private void setAndDirty( int slot, @Nonnull ItemStack stack ) + { + this.inventory.setStack( slot, stack ); this.inventory.markDirty(); } @Override @Nonnull - public ItemStack store(int slot, @Nonnull ItemStack stack, boolean simulate) { - if (stack.isEmpty() || !this.inventory.isValid(slot, stack)) { + public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ) + { + if( stack.isEmpty() || !this.inventory.isValid( slot, stack ) ) + { return stack; } - ItemStack existing = this.inventory.getStack(slot); - if (existing.isEmpty()) { - int limit = Math.min(stack.getMaxCount(), this.inventory.getMaxCountPerStack()); - if (limit <= 0) { + ItemStack existing = this.inventory.getStack( slot ); + if( existing.isEmpty() ) + { + int limit = Math.min( stack.getMaxCount(), this.inventory.getMaxCountPerStack() ); + if( limit <= 0 ) + { return stack; } - if (stack.getCount() < limit) { - if (!simulate) { - this.setAndDirty(slot, stack); + if( stack.getCount() < limit ) + { + if( !simulate ) + { + this.setAndDirty( slot, stack ); } return ItemStack.EMPTY; - } else { + } + else + { stack = stack.copy(); - ItemStack insert = stack.split(limit); - if (!simulate) { - this.setAndDirty(slot, insert); + ItemStack insert = stack.split( limit ); + if( !simulate ) + { + this.setAndDirty( slot, insert ); } return stack; } - } else if (areStackable(stack, existing)) { - int limit = Math.min(existing.getMaxCount(), this.inventory.getMaxCountPerStack()) - existing.getCount(); - if (limit <= 0) { + } + else if( areStackable( stack, existing ) ) + { + int limit = Math.min( existing.getMaxCount(), this.inventory.getMaxCountPerStack() ) - existing.getCount(); + if( limit <= 0 ) + { return stack; } - if (stack.getCount() < limit) { - if (!simulate) { - existing.increment(stack.getCount()); - this.setAndDirty(slot, existing); + if( stack.getCount() < limit ) + { + if( !simulate ) + { + existing.increment( stack.getCount() ); + this.setAndDirty( slot, existing ); } return ItemStack.EMPTY; - } else { + } + else + { stack = stack.copy(); - stack.decrement(limit); - if (!simulate) { - existing.increment(limit); - this.setAndDirty(slot, existing); + stack.decrement( limit ); + if( !simulate ) + { + existing.increment( limit ); + this.setAndDirty( slot, existing ); } return stack; } - } else { + } + else + { return stack; } } } - class SidedInventoryWrapper extends InventoryWrapper { + class SidedInventoryWrapper extends InventoryWrapper + { private final SidedInventory inventory; private final Direction facing; - SidedInventoryWrapper(SidedInventory inventory, Direction facing) { - super(inventory); + SidedInventoryWrapper( SidedInventory inventory, Direction facing ) + { + super( inventory ); this.inventory = inventory; this.facing = facing; } @Override - protected boolean canExtract(int slot, ItemStack stack) { - return super.canExtract(slot, stack) && this.inventory.canExtract(slot, stack, this.facing); + protected boolean canExtract( int slot, ItemStack stack ) + { + return super.canExtract( slot, stack ) && this.inventory.canExtract( slot, stack, this.facing ); } @Override - public int size() { - return this.inventory.getAvailableSlots(this.facing).length; + public int size() + { + return this.inventory.getAvailableSlots( this.facing ).length; } @Nonnull @Override - public ItemStack take(int slot, int limit, @Nonnull ItemStack filter, boolean simulate) { - int[] slots = this.inventory.getAvailableSlots(this.facing); - return slot >= 0 && slot < slots.length ? super.take(slots[slot], limit, filter, simulate) : ItemStack.EMPTY; + public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ) + { + int[] slots = this.inventory.getAvailableSlots( this.facing ); + return slot >= 0 && slot < slots.length ? super.take( slots[slot], limit, filter, simulate ) : ItemStack.EMPTY; } @Nonnull @Override - public ItemStack store(int slot, @Nonnull ItemStack stack, boolean simulate) { - int[] slots = this.inventory.getAvailableSlots(this.facing); - if (slot < 0 || slot >= slots.length) { + public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ) + { + int[] slots = this.inventory.getAvailableSlots( this.facing ); + if( slot < 0 || slot >= slots.length ) + { return stack; } int mappedSlot = slots[slot]; - if (!this.inventory.canInsert(slot, stack, this.facing)) { + if( !this.inventory.canInsert( slot, stack, this.facing ) ) + { return stack; } - return super.store(mappedSlot, stack, simulate); + return super.store( mappedSlot, stack, simulate ); } } - class View implements ItemStorage { + class View implements ItemStorage + { private final ItemStorage parent; private final int start; private final int size; - View(ItemStorage parent, int start, int size) { + View( ItemStorage parent, int start, int size ) + { this.parent = parent; this.start = start; this.size = size; } @Override - public int size() { + public int size() + { return this.size; } @Override @Nonnull - public ItemStack getStack(int slot) { - if (slot < this.start || slot >= this.start + this.size) { + public ItemStack getStack( int slot ) + { + if( slot < this.start || slot >= this.start + this.size ) + { return ItemStack.EMPTY; } - return this.parent.getStack(slot - this.start ); + return this.parent.getStack( slot - this.start ); } @Nonnull @Override - public ItemStack take(int slot, int limit, @Nonnull ItemStack filter, boolean simulate) { - if (slot < this.start || slot >= this.start + this.size) { + public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ) + { + if( slot < this.start || slot >= this.start + this.size ) + { return ItemStack.EMPTY; } - return this.parent.take(slot - this.start, limit, filter, simulate); + return this.parent.take( slot - this.start, limit, filter, simulate ); } @Nonnull @Override - public ItemStack store(int slot, @Nonnull ItemStack stack, boolean simulate) { - if (slot < this.start || slot >= this.start + this.size) { + public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ) + { + if( slot < this.start || slot >= this.start + this.size ) + { return stack; } - return this.parent.store(slot - this.start, stack, simulate); + return this.parent.store( slot - this.start, stack, simulate ); } @Override - public ItemStorage view(int start, int size) { - return new View(this.parent, this.start + start, size); + public ItemStorage view( int start, int size ) + { + return new View( this.parent, this.start + start, size ); } } } diff --git a/src/main/java/dan200/computercraft/shared/util/NBTUtil.java b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java index f2cef4ae2..99f39d71c 100644 --- a/src/main/java/dan200/computercraft/shared/util/NBTUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java @@ -6,6 +6,12 @@ package dan200.computercraft.shared.util; +import dan200.computercraft.ComputerCraft; +import net.minecraft.nbt.*; +import org.apache.commons.codec.binary.Hex; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; @@ -15,24 +21,8 @@ import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import dan200.computercraft.ComputerCraft; -import org.apache.commons.codec.binary.Hex; - -import net.minecraft.nbt.AbstractNumberTag; -import net.minecraft.nbt.ByteArrayTag; -import net.minecraft.nbt.ByteTag; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.IntArrayTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; - -public final class NBTUtil { +public final class NBTUtil +{ public static final int TAG_END = 0; public static final int TAG_BYTE = 1; public static final int TAG_SHORT = 2; @@ -50,191 +40,233 @@ public final class NBTUtil { private NBTUtil() {} - private static Tag toNBTTag(Object object) { - if (object == null) { + private static Tag toNBTTag( Object object ) + { + if( object == null ) + { return null; } - if (object instanceof Boolean) { - return ByteTag.of((byte) ((boolean) (Boolean) object ? 1 : 0)); + if( object instanceof Boolean ) + { + return ByteTag.of( (byte) ((boolean) (Boolean) object ? 1 : 0) ); } - if (object instanceof Number) { - return DoubleTag.of(((Number) object).doubleValue()); + if( object instanceof Number ) + { + return DoubleTag.of( ((Number) object).doubleValue() ); } - if (object instanceof String) { - return StringTag.of(object.toString()); + if( object instanceof String ) + { + return StringTag.of( object.toString() ); } - if (object instanceof Map) { + if( object instanceof Map ) + { Map m = (Map) object; CompoundTag nbt = new CompoundTag(); int i = 0; - for (Map.Entry entry : m.entrySet()) { - Tag key = toNBTTag(entry.getKey()); - Tag value = toNBTTag(entry.getKey()); - if (key != null && value != null) { - nbt.put("k" + i, key); - nbt.put("v" + i, value); + for( Map.Entry entry : m.entrySet() ) + { + Tag key = toNBTTag( entry.getKey() ); + Tag value = toNBTTag( entry.getKey() ); + if( key != null && value != null ) + { + nbt.put( "k" + i, key ); + nbt.put( "v" + i, value ); i++; } } - nbt.putInt("len", m.size()); + nbt.putInt( "len", m.size() ); return nbt; } return null; } - public static CompoundTag encodeObjects(Object[] objects) { - if (objects == null || objects.length <= 0) { + public static CompoundTag encodeObjects( Object[] objects ) + { + if( objects == null || objects.length <= 0 ) + { return null; } CompoundTag nbt = new CompoundTag(); - nbt.putInt("len", objects.length); - for (int i = 0; i < objects.length; i++) { - Tag child = toNBTTag(objects[i]); - if (child != null) { - nbt.put(Integer.toString(i), child); + nbt.putInt( "len", objects.length ); + for( int i = 0; i < objects.length; i++ ) + { + Tag child = toNBTTag( objects[i] ); + if( child != null ) + { + nbt.put( Integer.toString( i ), child ); } } return nbt; } - private static Object fromNBTTag(Tag tag) { - if (tag == null) { + private static Object fromNBTTag( Tag tag ) + { + if( tag == null ) + { return null; } - switch (tag.getType()) { - case TAG_BYTE: - return ((ByteTag) tag).getByte() > 0; - case TAG_DOUBLE: - return ((DoubleTag) tag).getDouble(); - default: - case TAG_STRING: - return tag.asString(); - case TAG_COMPOUND: { - CompoundTag c = (CompoundTag) tag; - int len = c.getInt("len"); - Map map = new HashMap<>(len); - for (int i = 0; i < len; i++) { - Object key = fromNBTTag(c.get("k" + i)); - Object value = fromNBTTag(c.get("v" + i)); - if (key != null && value != null) { - map.put(key, value); + switch( tag.getType() ) + { + case TAG_BYTE: + return ((ByteTag) tag).getByte() > 0; + case TAG_DOUBLE: + return ((DoubleTag) tag).getDouble(); + default: + case TAG_STRING: + return tag.asString(); + case TAG_COMPOUND: + { + CompoundTag c = (CompoundTag) tag; + int len = c.getInt( "len" ); + Map map = new HashMap<>( len ); + for( int i = 0; i < len; i++ ) + { + Object key = fromNBTTag( c.get( "k" + i ) ); + Object value = fromNBTTag( c.get( "v" + i ) ); + if( key != null && value != null ) + { + map.put( key, value ); + } } + return map; } - return map; - } } } - public static Object toLua(Tag tag) { - if (tag == null) { + public static Object toLua( Tag tag ) + { + if( tag == null ) + { return null; } byte typeID = tag.getType(); - switch (typeID) { - case TAG_BYTE: - case TAG_SHORT: - case TAG_INT: - case TAG_LONG: - return ((AbstractNumberTag) tag).getLong(); - case TAG_FLOAT: - case TAG_DOUBLE: - return ((AbstractNumberTag) tag).getDouble(); - case TAG_STRING: // String - return tag.asString(); - case TAG_COMPOUND: // Compound + switch( typeID ) { - CompoundTag compound = (CompoundTag) tag; - Map map = new HashMap<>(compound.getSize()); - for (String key : compound.getKeys()) { - Object value = toLua(compound.get(key)); - if (value != null) { - map.put(key, value); + case TAG_BYTE: + case TAG_SHORT: + case TAG_INT: + case TAG_LONG: + return ((AbstractNumberTag) tag).getLong(); + case TAG_FLOAT: + case TAG_DOUBLE: + return ((AbstractNumberTag) tag).getDouble(); + case TAG_STRING: // String + return tag.asString(); + case TAG_COMPOUND: // Compound + { + CompoundTag compound = (CompoundTag) tag; + Map map = new HashMap<>( compound.getSize() ); + for( String key : compound.getKeys() ) + { + Object value = toLua( compound.get( key ) ); + if( value != null ) + { + map.put( key, value ); + } } + return map; } - return map; - } - case TAG_LIST: { - ListTag list = (ListTag) tag; - Map map = new HashMap<>(list.size()); - for (int i = 0; i < list.size(); i++) { - map.put(i, toLua(list.get(i))); + case TAG_LIST: + { + ListTag list = (ListTag) tag; + Map map = new HashMap<>( list.size() ); + for( int i = 0; i < list.size(); i++ ) + { + map.put( i, toLua( list.get( i ) ) ); + } + return map; } - return map; - } - case TAG_BYTE_ARRAY: { - byte[] array = ((ByteArrayTag) tag).getByteArray(); - Map map = new HashMap<>(array.length); - for (int i = 0; i < array.length; i++) { - map.put(i + 1, array[i]); + case TAG_BYTE_ARRAY: + { + byte[] array = ((ByteArrayTag) tag).getByteArray(); + Map map = new HashMap<>( array.length ); + for( int i = 0; i < array.length; i++ ) + { + map.put( i + 1, array[i] ); + } + return map; } - return map; - } - case TAG_INT_ARRAY: { - int[] array = ((IntArrayTag) tag).getIntArray(); - Map map = new HashMap<>(array.length); - for (int i = 0; i < array.length; i++) { - map.put(i + 1, array[i]); + case TAG_INT_ARRAY: + { + int[] array = ((IntArrayTag) tag).getIntArray(); + Map map = new HashMap<>( array.length ); + for( int i = 0; i < array.length; i++ ) + { + map.put( i + 1, array[i] ); + } + return map; } - return map; - } - default: - return null; + default: + return null; } } - public static Object[] decodeObjects(CompoundTag tag) { - int len = tag.getInt("len"); - if (len <= 0) { + public static Object[] decodeObjects( CompoundTag tag ) + { + int len = tag.getInt( "len" ); + if( len <= 0 ) + { return null; } Object[] objects = new Object[len]; - for (int i = 0; i < len; i++) { - String key = Integer.toString(i); - if (tag.contains(key)) { - objects[i] = fromNBTTag(tag.get(key)); + for( int i = 0; i < len; i++ ) + { + String key = Integer.toString( i ); + if( tag.contains( key ) ) + { + objects[i] = fromNBTTag( tag.get( key ) ); } } return objects; } @Nullable - public static String getNBTHash(@Nullable CompoundTag tag) { - if (tag == null) { + public static String getNBTHash( @Nullable CompoundTag tag ) + { + if( tag == null ) + { return null; } - try { - MessageDigest digest = MessageDigest.getInstance("MD5"); - DataOutput output = new DataOutputStream(new DigestOutputStream(digest)); - NbtIo.write(tag, output); + try + { + MessageDigest digest = MessageDigest.getInstance( "MD5" ); + DataOutput output = new DataOutputStream( new DigestOutputStream( digest ) ); + NbtIo.write( tag, output ); byte[] hash = digest.digest(); - return new String(Hex.encodeHex(hash)); - } catch (NoSuchAlgorithmException | IOException e) { - ComputerCraft.log.error("Cannot hash NBT", e); + return new String( Hex.encodeHex( hash ) ); + } + catch( NoSuchAlgorithmException | IOException e ) + { + ComputerCraft.log.error( "Cannot hash NBT", e ); return null; } } - private static final class DigestOutputStream extends OutputStream { + private static final class DigestOutputStream extends OutputStream + { private final MessageDigest digest; - DigestOutputStream(MessageDigest digest) { + DigestOutputStream( MessageDigest digest ) + { this.digest = digest; } @Override - public void write(int b) { - this.digest.update((byte) b); + public void write( int b ) + { + this.digest.update( (byte) b ); } @Override - public void write(@Nonnull byte[] b, int off, int len) { - this.digest.update(b, off, len); + public void write( @Nonnull byte[] b, int off, int len ) + { + this.digest.update( b, off, len ); } } } diff --git a/src/main/java/dan200/computercraft/shared/util/Palette.java b/src/main/java/dan200/computercraft/shared/util/Palette.java index f208931c9..23f5654a0 100644 --- a/src/main/java/dan200/computercraft/shared/util/Palette.java +++ b/src/main/java/dan200/computercraft/shared/util/Palette.java @@ -9,75 +9,95 @@ package dan200.computercraft.shared.util; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.PacketByteBuf; -public class Palette { +public class Palette +{ public static final Palette DEFAULT = new Palette(); private static final int PALETTE_SIZE = 16; private final double[][] colours = new double[PALETTE_SIZE][3]; - public Palette() { + public Palette() + { // Get the default palette this.resetColours(); } - public void resetColours() { - for (int i = 0; i < Colour.VALUES.length; i++) { - this.resetColour(i); + public void resetColours() + { + for( int i = 0; i < Colour.VALUES.length; i++ ) + { + this.resetColour( i ); } } - public void resetColour(int i) { - if (i >= 0 && i < this.colours.length) { - this.setColour(i, Colour.VALUES[i]); + public void resetColour( int i ) + { + if( i >= 0 && i < this.colours.length ) + { + this.setColour( i, Colour.VALUES[i] ); } } - public void setColour(int i, Colour colour) { - this.setColour(i, colour.getR(), colour.getG(), colour.getB()); + public void setColour( int i, Colour colour ) + { + this.setColour( i, colour.getR(), colour.getG(), colour.getB() ); } - public void setColour(int i, double r, double g, double b) { - if (i >= 0 && i < this.colours.length) { + public void setColour( int i, double r, double g, double b ) + { + if( i >= 0 && i < this.colours.length ) + { this.colours[i][0] = r; this.colours[i][1] = g; this.colours[i][2] = b; } } - public double[] getColour(int i) { - if (i >= 0 && i < this.colours.length) { + public double[] getColour( int i ) + { + if( i >= 0 && i < this.colours.length ) + { return this.colours[i]; } return null; } - public void write(PacketByteBuf buffer) { - for (double[] colour : this.colours) { - for (double channel : colour) { - buffer.writeByte((int) (channel * 0xFF) & 0xFF); + public void write( PacketByteBuf buffer ) + { + for( double[] colour : this.colours ) + { + for( double channel : colour ) + { + buffer.writeByte( (int) (channel * 0xFF) & 0xFF ); } } } - public void read(PacketByteBuf buffer) { - for (double[] colour : this.colours) { - for (int i = 0; i < colour.length; i++) { + public void read( PacketByteBuf buffer ) + { + for( double[] colour : this.colours ) + { + for( int i = 0; i < colour.length; i++ ) + { colour[i] = (buffer.readByte() & 0xFF) / 255.0; } } } - public CompoundTag writeToNBT(CompoundTag nbt) { + public CompoundTag writeToNBT( CompoundTag nbt ) + { int[] rgb8 = new int[this.colours.length]; - for (int i = 0; i < this.colours.length; i++) { - rgb8[i] = encodeRGB8(this.colours[i]); + for( int i = 0; i < this.colours.length; i++ ) + { + rgb8[i] = encodeRGB8( this.colours[i] ); } - nbt.putIntArray("term_palette", rgb8); + nbt.putIntArray( "term_palette", rgb8 ); return nbt; } - public static int encodeRGB8(double[] rgb) { + public static int encodeRGB8( double[] rgb ) + { int r = (int) (rgb[0] * 255) & 0xFF; int g = (int) (rgb[1] * 255) & 0xFF; int b = (int) (rgb[2] * 255) & 0xFF; @@ -85,26 +105,31 @@ public class Palette { return (r << 16) | (g << 8) | b; } - public void readFromNBT(CompoundTag nbt) { - if (!nbt.contains("term_palette")) { + public void readFromNBT( CompoundTag nbt ) + { + if( !nbt.contains( "term_palette" ) ) + { return; } - int[] rgb8 = nbt.getIntArray("term_palette"); + int[] rgb8 = nbt.getIntArray( "term_palette" ); - if (rgb8.length != this.colours.length) { + if( rgb8.length != this.colours.length ) + { return; } - for (int i = 0; i < this.colours.length; i++) { - this.colours[i] = decodeRGB8(rgb8[i]); + for( int i = 0; i < this.colours.length; i++ ) + { + this.colours[i] = decodeRGB8( rgb8[i] ); } } - public static double[] decodeRGB8(int rgb) { + public static double[] decodeRGB8( int rgb ) + { return new double[] { ((rgb >> 16) & 0xFF) / 255.0f, ((rgb >> 8) & 0xFF) / 255.0f, (rgb & 0xFF) / 255.0f, - }; + }; } } diff --git a/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java b/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java index 8851d1ea8..8093458c2 100644 --- a/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java @@ -6,9 +6,6 @@ package dan200.computercraft.shared.util; -import java.util.Map; -import java.util.Set; - import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.gson.JsonArray; @@ -16,93 +13,112 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import dan200.computercraft.shared.computer.core.ComputerFamily; - import net.minecraft.recipe.Ingredient; import net.minecraft.util.JsonHelper; import net.minecraft.util.collection.DefaultedList; +import java.util.Map; +import java.util.Set; + // TODO: Replace some things with Forge?? -public final class RecipeUtil { +public final class RecipeUtil +{ private RecipeUtil() {} - public static ShapedTemplate getTemplate(JsonObject json) { + public static ShapedTemplate getTemplate( JsonObject json ) + { Map ingMap = Maps.newHashMap(); - for (Map.Entry entry : JsonHelper.getObject(json, "key") - .entrySet()) { - if (entry.getKey() - .length() != 1) { - throw new JsonSyntaxException("Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only)."); + for( Map.Entry entry : JsonHelper.getObject( json, "key" ) + .entrySet() ) + { + if( entry.getKey() + .length() != 1 ) + { + throw new JsonSyntaxException( "Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only)." ); } - if (" ".equals(entry.getKey())) { - throw new JsonSyntaxException("Invalid key entry: ' ' is a reserved symbol."); + if( " ".equals( entry.getKey() ) ) + { + throw new JsonSyntaxException( "Invalid key entry: ' ' is a reserved symbol." ); } - ingMap.put(entry.getKey() - .charAt(0), Ingredient.fromJson(entry.getValue())); + ingMap.put( entry.getKey() + .charAt( 0 ), Ingredient.fromJson( entry.getValue() ) ); } - ingMap.put(' ', Ingredient.EMPTY); + ingMap.put( ' ', Ingredient.EMPTY ); - JsonArray patternJ = JsonHelper.getArray(json, "pattern"); + JsonArray patternJ = JsonHelper.getArray( json, "pattern" ); - if (patternJ.size() == 0) { - throw new JsonSyntaxException("Invalid pattern: empty pattern not allowed"); + if( patternJ.size() == 0 ) + { + throw new JsonSyntaxException( "Invalid pattern: empty pattern not allowed" ); } String[] pattern = new String[patternJ.size()]; - for (int x = 0; x < pattern.length; x++) { - String line = JsonHelper.asString(patternJ.get(x), "pattern[" + x + "]"); - if (x > 0 && pattern[0].length() != line.length()) { - throw new JsonSyntaxException("Invalid pattern: each row must be the same width"); + for( int x = 0; x < pattern.length; x++ ) + { + String line = JsonHelper.asString( patternJ.get( x ), "pattern[" + x + "]" ); + if( x > 0 && pattern[0].length() != line.length() ) + { + throw new JsonSyntaxException( "Invalid pattern: each row must be the same width" ); } pattern[x] = line; } int width = pattern[0].length(); int height = pattern.length; - DefaultedList ingredients = DefaultedList.ofSize(width * height, Ingredient.EMPTY); + DefaultedList ingredients = DefaultedList.ofSize( width * height, Ingredient.EMPTY ); - Set missingKeys = Sets.newHashSet(ingMap.keySet()); - missingKeys.remove(' '); + Set missingKeys = Sets.newHashSet( ingMap.keySet() ); + missingKeys.remove( ' ' ); int i = 0; - for (String line : pattern) { - for (char chr : line.toCharArray()) { - Ingredient ing = ingMap.get(chr); - if (ing == null) { - throw new JsonSyntaxException("Pattern references symbol '" + chr + "' but it's not defined in the key"); + for( String line : pattern ) + { + for( char chr : line.toCharArray() ) + { + Ingredient ing = ingMap.get( chr ); + if( ing == null ) + { + throw new JsonSyntaxException( "Pattern references symbol '" + chr + "' but it's not defined in the key" ); } - ingredients.set(i++, ing); - missingKeys.remove(chr); + ingredients.set( i++, ing ); + missingKeys.remove( chr ); } } - if (!missingKeys.isEmpty()) { - throw new JsonSyntaxException("Key defines symbols that aren't used in pattern: " + missingKeys); + if( !missingKeys.isEmpty() ) + { + throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + missingKeys ); } - return new ShapedTemplate(width, height, ingredients); + return new ShapedTemplate( width, height, ingredients ); } - public static ComputerFamily getFamily(JsonObject json, String name) { - String familyName = JsonHelper.getString(json, name); - for (ComputerFamily family : ComputerFamily.values()) { - if (family.name() - .equalsIgnoreCase(familyName)) { + public static ComputerFamily getFamily( JsonObject json, String name ) + { + String familyName = JsonHelper.getString( json, name ); + for( ComputerFamily family : ComputerFamily.values() ) + { + if( family.name() + .equalsIgnoreCase( familyName ) ) + { return family; } } - throw new JsonSyntaxException("Unknown computer family '" + familyName + "' for field " + name); + throw new JsonSyntaxException( "Unknown computer family '" + familyName + "' for field " + name ); } - public static class ShapedTemplate { + public static class ShapedTemplate + { public final int width; public final int height; public final DefaultedList ingredients; - public ShapedTemplate(int width, int height, DefaultedList ingredients) { + public ShapedTemplate( int width, int height, DefaultedList ingredients ) + { this.width = width; this.height = height; this.ingredients = ingredients; diff --git a/src/main/java/dan200/computercraft/shared/util/RecordUtil.java b/src/main/java/dan200/computercraft/shared/util/RecordUtil.java index 9fcb82bae..30de0b841 100644 --- a/src/main/java/dan200/computercraft/shared/util/RecordUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/RecordUtil.java @@ -9,17 +9,18 @@ package dan200.computercraft.shared.util; import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.client.PlayRecordClientMessage; - import net.minecraft.sound.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public final class RecordUtil { +public final class RecordUtil +{ private RecordUtil() {} - public static void playRecord(SoundEvent record, String recordInfo, World world, BlockPos pos) { - NetworkMessage packet = record != null ? new PlayRecordClientMessage(pos, record, recordInfo) : new PlayRecordClientMessage(pos); - NetworkHandler.sendToAllAround(packet, world, Vec3d.ofCenter(pos), 64); + public static void playRecord( SoundEvent record, String recordInfo, World world, BlockPos pos ) + { + NetworkMessage packet = record != null ? new PlayRecordClientMessage( pos, record, recordInfo ) : new PlayRecordClientMessage( pos ); + NetworkHandler.sendToAllAround( packet, world, Vec3d.ofCenter( pos ), 64 ); } } diff --git a/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java b/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java index 1e6bf0f77..ca27dcde5 100644 --- a/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java @@ -11,12 +11,14 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public final class RedstoneUtil { - public static void propagateRedstoneOutput(World world, BlockPos pos, Direction side) { +public final class RedstoneUtil +{ + public static void propagateRedstoneOutput( World world, BlockPos pos, Direction side ) + { // Propagate ordinary output. See BlockRedstoneDiode.notifyNeighbors - BlockState block = world.getBlockState(pos); - BlockPos neighbourPos = pos.offset(side); - world.updateNeighbor(neighbourPos, block.getBlock(), pos); - world.updateNeighborsExcept(neighbourPos, block.getBlock(), side.getOpposite()); + BlockState block = world.getBlockState( pos ); + BlockPos neighbourPos = pos.offset( side ); + world.updateNeighbor( neighbourPos, block.getBlock(), pos ); + world.updateNeighborsExcept( neighbourPos, block.getBlock(), side.getOpposite() ); } } diff --git a/src/main/java/dan200/computercraft/shared/util/SingleIntArray.java b/src/main/java/dan200/computercraft/shared/util/SingleIntArray.java index 89355c1eb..7479b2e37 100644 --- a/src/main/java/dan200/computercraft/shared/util/SingleIntArray.java +++ b/src/main/java/dan200/computercraft/shared/util/SingleIntArray.java @@ -9,20 +9,24 @@ package dan200.computercraft.shared.util; import net.minecraft.screen.PropertyDelegate; @FunctionalInterface -public interface SingleIntArray extends PropertyDelegate { +public interface SingleIntArray extends PropertyDelegate +{ @Override - default int get(int property) { + default int get( int property ) + { return property == 0 ? this.get() : 0; } int get(); @Override - default void set(int property, int value) { + default void set( int property, int value ) + { } @Override - default int size() { + default int size() + { return 1; } } diff --git a/src/main/java/dan200/computercraft/shared/util/StringUtil.java b/src/main/java/dan200/computercraft/shared/util/StringUtil.java index c5ccb6a4d..2c8dd68b8 100644 --- a/src/main/java/dan200/computercraft/shared/util/StringUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/StringUtil.java @@ -8,29 +8,37 @@ package dan200.computercraft.shared.util; import javax.annotation.Nullable; -public final class StringUtil { +public final class StringUtil +{ private StringUtil() {} - public static String normaliseLabel(String label) { - if (label == null) { + public static String normaliseLabel( String label ) + { + if( label == null ) + { return null; } - int length = Math.min(32, label.length()); - StringBuilder builder = new StringBuilder(length); - for (int i = 0; i < length; i++) { - char c = label.charAt(i); - if ((c >= ' ' && c <= '~') || (c >= 161 && c <= 172) || (c >= 174 && c <= 255)) { - builder.append(c); - } else { - builder.append('?'); + int length = Math.min( 32, label.length() ); + StringBuilder builder = new StringBuilder( length ); + for( int i = 0; i < length; i++ ) + { + char c = label.charAt( i ); + if( (c >= ' ' && c <= '~') || (c >= 161 && c <= 172) || (c >= 174 && c <= 255) ) + { + builder.append( c ); + } + else + { + builder.append( '?' ); } } return builder.toString(); } - public static String toString(@Nullable Object value) { + public static String toString( @Nullable Object value ) + { return value == null ? "" : value.toString(); } } diff --git a/src/main/java/dan200/computercraft/shared/util/ThreadUtils.java b/src/main/java/dan200/computercraft/shared/util/ThreadUtils.java index d63950abd..24f487d4f 100644 --- a/src/main/java/dan200/computercraft/shared/util/ThreadUtils.java +++ b/src/main/java/dan200/computercraft/shared/util/ThreadUtils.java @@ -6,18 +6,20 @@ package dan200.computercraft.shared.util; -import java.util.concurrent.ThreadFactory; - import com.google.common.util.concurrent.ThreadFactoryBuilder; import dan200.computercraft.ComputerCraft; +import java.util.concurrent.ThreadFactory; + /** * Provides some utilities to create thread groups. */ -public final class ThreadUtils { - private static final ThreadGroup baseGroup = new ThreadGroup("ComputerCraft"); +public final class ThreadUtils +{ + private static final ThreadGroup baseGroup = new ThreadGroup( "ComputerCraft" ); - private ThreadUtils() { + private ThreadUtils() + { } /** @@ -25,7 +27,8 @@ public final class ThreadUtils { * * @return The ComputerCraft group. */ - public static ThreadGroup group() { + public static ThreadGroup group() + { return baseGroup; } @@ -39,8 +42,9 @@ public final class ThreadUtils { * @return The constructed thread factory. * @see #builder(String) */ - public static ThreadFactory factory(String name) { - return builder(name).build(); + public static ThreadFactory factory( String name ) + { + return builder( name ).build(); } /** @@ -53,13 +57,14 @@ public final class ThreadUtils { * @return The constructed thread factory builder, which may be extended with other properties. * @see #factory(String) */ - public static ThreadFactoryBuilder builder(String name) { - ThreadGroup group = group(name); - return new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat(group.getName() - .replace("%", "%%") + "-%d") - .setUncaughtExceptionHandler((t, e) -> ComputerCraft.log.error("Exception in thread " + t.getName(), e)) - .setThreadFactory(x -> new Thread(group, x)); + public static ThreadFactoryBuilder builder( String name ) + { + ThreadGroup group = group( name ); + return new ThreadFactoryBuilder().setDaemon( true ) + .setNameFormat( group.getName() + .replace( "%", "%%" ) + "-%d" ) + .setUncaughtExceptionHandler( ( t, e ) -> ComputerCraft.log.error( "Exception in thread " + t.getName(), e ) ) + .setThreadFactory( x -> new Thread( group, x ) ); } /** @@ -68,7 +73,8 @@ public final class ThreadUtils { * @param name The group's name. This will be prefixed with "ComputerCraft-". * @return The constructed thread group. */ - public static ThreadGroup group(String name) { - return new ThreadGroup(baseGroup, baseGroup.getName() + "-" + name); + public static ThreadGroup group( String name ) + { + return new ThreadGroup( baseGroup, baseGroup.getName() + "-" + name ); } } diff --git a/src/main/java/dan200/computercraft/shared/util/TickScheduler.java b/src/main/java/dan200/computercraft/shared/util/TickScheduler.java index 4b4846bc3..98e3a8036 100644 --- a/src/main/java/dan200/computercraft/shared/util/TickScheduler.java +++ b/src/main/java/dan200/computercraft/shared/util/TickScheduler.java @@ -6,49 +6,55 @@ package dan200.computercraft.shared.util; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - import com.google.common.collect.MapMaker; import dan200.computercraft.shared.common.TileGeneric; - import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; + /** * We use this when modems and other peripherals change a block in a different thread. */ -public final class TickScheduler { - private static final Set toTick = Collections.newSetFromMap(new MapMaker().weakKeys() - .makeMap()); +public final class TickScheduler +{ + private static final Set toTick = Collections.newSetFromMap( new MapMaker().weakKeys() + .makeMap() ); - private TickScheduler() { + private TickScheduler() + { } - public static void schedule(TileGeneric tile) { + public static void schedule( TileGeneric tile ) + { World world = tile.getWorld(); - if (world != null && !world.isClient) { - toTick.add(tile); + if( world != null && !world.isClient ) + { + toTick.add( tile ); } } - public static void tick() { + public static void tick() + { Iterator iterator = toTick.iterator(); - while (iterator.hasNext()) { + while( iterator.hasNext() ) + { BlockEntity tile = iterator.next(); iterator.remove(); World world = tile.getWorld(); BlockPos pos = tile.getPos(); - if (world != null && pos != null && world.isChunkLoaded(pos) && world.getBlockEntity(pos) == tile) { + if( world != null && pos != null && world.isChunkLoaded( pos ) && world.getBlockEntity( pos ) == tile ) + { world.getBlockTickScheduler() - .schedule(pos, - tile.getCachedState() - .getBlock(), - 0); + .schedule( pos, + tile.getCachedState() + .getBlock(), + 0 ); } } } diff --git a/src/main/java/dan200/computercraft/shared/util/ValidatingSlot.java b/src/main/java/dan200/computercraft/shared/util/ValidatingSlot.java index 517cf63a1..aa1e50940 100644 --- a/src/main/java/dan200/computercraft/shared/util/ValidatingSlot.java +++ b/src/main/java/dan200/computercraft/shared/util/ValidatingSlot.java @@ -6,19 +6,22 @@ package dan200.computercraft.shared.util; -import javax.annotation.Nonnull; - import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.slot.Slot; -public class ValidatingSlot extends Slot { - public ValidatingSlot(Inventory inventoryIn, int index, int xPosition, int yPosition) { - super(inventoryIn, index, xPosition, yPosition); +import javax.annotation.Nonnull; + +public class ValidatingSlot extends Slot +{ + public ValidatingSlot( Inventory inventoryIn, int index, int xPosition, int yPosition ) + { + super( inventoryIn, index, xPosition, yPosition ); } @Override - public boolean canInsert(@Nonnull ItemStack stack) { + public boolean canInsert( @Nonnull ItemStack stack ) + { return true; // inventory.isItemValidForSlot( slotNumber, stack ); } } diff --git a/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java b/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java index 6606b5f88..7703ab8ef 100644 --- a/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java +++ b/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java @@ -20,10 +20,12 @@ import net.minecraft.world.WorldAccess; * * I'm fairly sure this exists on 1.14, but it's a useful convenience wrapper to have on 1.13. */ -public final class WaterloggableHelpers { +public final class WaterloggableHelpers +{ public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED; - private WaterloggableHelpers() { + private WaterloggableHelpers() + { } /** @@ -32,8 +34,9 @@ public final class WaterloggableHelpers { * @param state The current state * @return This waterlogged block's current fluid */ - public static FluidState getWaterloggedFluidState(BlockState state) { - return state.get(WATERLOGGED) ? Fluids.WATER.getStill(false) : Fluids.EMPTY.getDefaultState(); + public static FluidState getWaterloggedFluidState( BlockState state ) + { + return state.get( WATERLOGGED ) ? Fluids.WATER.getStill( false ) : Fluids.EMPTY.getDefaultState(); } /** @@ -41,18 +44,21 @@ public final class WaterloggableHelpers { * * @param state The current state * @param world The position of this block - * @param pos The world this block exists in + * @param pos The world this block exists in */ - public static void updateWaterloggedPostPlacement(BlockState state, WorldAccess world, BlockPos pos) { - if (state.get(WATERLOGGED)) { + public static void updateWaterloggedPostPlacement( BlockState state, WorldAccess world, BlockPos pos ) + { + if( state.get( WATERLOGGED ) ) + { world.getFluidTickScheduler() - .schedule(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + .schedule( pos, Fluids.WATER, Fluids.WATER.getTickRate( world ) ); } } - public static boolean getWaterloggedStateForPlacement(ItemPlacementContext context) { + public static boolean getWaterloggedStateForPlacement( ItemPlacementContext context ) + { return context.getWorld() - .getFluidState(context.getBlockPos()) - .getFluid() == Fluids.WATER; + .getFluidState( context.getBlockPos() ) + .getFluid() == Fluids.WATER; } } diff --git a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java index 52f37c3ad..6e0ff4490 100644 --- a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java @@ -6,21 +6,9 @@ package dan200.computercraft.shared.util; -import java.util.List; -import java.util.Map; - -import javax.annotation.Nonnull; - import com.google.common.base.Predicate; import com.google.common.collect.MapMaker; -import org.apache.commons.lang3.tuple.Pair; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityDimensions; -import net.minecraft.entity.EntityPose; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.*; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.hit.HitResult; @@ -31,25 +19,36 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.RaycastContext; import net.minecraft.world.World; +import org.apache.commons.lang3.tuple.Pair; -public final class WorldUtil { - @SuppressWarnings ("Guava") private static final Predicate CAN_COLLIDE = x -> x != null && x.isAlive() && x.collides(); +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Map; + +public final class WorldUtil +{ + @SuppressWarnings( "Guava" ) + private static final Predicate CAN_COLLIDE = x -> x != null && x.isAlive() && x.collides(); private static final Map entityCache = new MapMaker().weakKeys() - .weakValues() - .makeMap(); + .weakValues() + .makeMap(); - public static boolean isLiquidBlock(World world, BlockPos pos) { - if (!World.isInBuildLimit(pos)) { + public static boolean isLiquidBlock( World world, BlockPos pos ) + { + if( !World.isInBuildLimit( pos ) ) + { return false; } - return world.getBlockState(pos) - .getMaterial() - .isLiquid(); + return world.getBlockState( pos ) + .getMaterial() + .isLiquid(); } - public static boolean isVecInside(VoxelShape shape, Vec3d vec) { - if (shape.isEmpty()) { + public static boolean isVecInside( VoxelShape shape, Vec3d vec ) + { + if( shape.isEmpty() ) + { return false; } // AxisAlignedBB.contains, but without strict inequalities. @@ -57,111 +56,132 @@ public final class WorldUtil { return vec.x >= bb.minX && vec.x <= bb.maxX && vec.y >= bb.minY && vec.y <= bb.maxY && vec.z >= bb.minZ && vec.z <= bb.maxZ; } - public static Pair rayTraceEntities(World world, Vec3d vecStart, Vec3d vecDir, double distance) { - Vec3d vecEnd = vecStart.add(vecDir.x * distance, vecDir.y * distance, vecDir.z * distance); + public static Pair rayTraceEntities( World world, Vec3d vecStart, Vec3d vecDir, double distance ) + { + Vec3d vecEnd = vecStart.add( vecDir.x * distance, vecDir.y * distance, vecDir.z * distance ); // Raycast for blocks - Entity collisionEntity = getEntity(world); - collisionEntity.updatePosition(vecStart.x, vecStart.y, vecStart.z); - RaycastContext context = new RaycastContext(vecStart, - vecEnd, - RaycastContext.ShapeType.COLLIDER, - RaycastContext.FluidHandling.NONE, - collisionEntity); - HitResult result = world.raycast(context); - if (result != null && result.getType() == HitResult.Type.BLOCK) { - distance = vecStart.distanceTo(result.getPos()); - vecEnd = vecStart.add(vecDir.x * distance, vecDir.y * distance, vecDir.z * distance); + Entity collisionEntity = getEntity( world ); + collisionEntity.updatePosition( vecStart.x, vecStart.y, vecStart.z ); + RaycastContext context = new RaycastContext( vecStart, + vecEnd, + RaycastContext.ShapeType.COLLIDER, + RaycastContext.FluidHandling.NONE, + collisionEntity ); + HitResult result = world.raycast( context ); + if( result != null && result.getType() == HitResult.Type.BLOCK ) + { + distance = vecStart.distanceTo( result.getPos() ); + vecEnd = vecStart.add( vecDir.x * distance, vecDir.y * distance, vecDir.z * distance ); } // Check for entities - float xStretch = Math.abs(vecDir.x) > 0.25f ? 0.0f : 1.0f; - float yStretch = Math.abs(vecDir.y) > 0.25f ? 0.0f : 1.0f; - float zStretch = Math.abs(vecDir.z) > 0.25f ? 0.0f : 1.0f; - Box bigBox = new Box(Math.min(vecStart.x, vecEnd.x) - 0.375f * xStretch, - Math.min(vecStart.y, vecEnd.y) - 0.375f * yStretch, - Math.min(vecStart.z, vecEnd.z) - 0.375f * zStretch, - Math.max(vecStart.x, vecEnd.x) + 0.375f * xStretch, - Math.max(vecStart.y, vecEnd.y) + 0.375f * yStretch, - Math.max(vecStart.z, vecEnd.z) + 0.375f * zStretch); + float xStretch = Math.abs( vecDir.x ) > 0.25f ? 0.0f : 1.0f; + float yStretch = Math.abs( vecDir.y ) > 0.25f ? 0.0f : 1.0f; + float zStretch = Math.abs( vecDir.z ) > 0.25f ? 0.0f : 1.0f; + Box bigBox = new Box( Math.min( vecStart.x, vecEnd.x ) - 0.375f * xStretch, + Math.min( vecStart.y, vecEnd.y ) - 0.375f * yStretch, + Math.min( vecStart.z, vecEnd.z ) - 0.375f * zStretch, + Math.max( vecStart.x, vecEnd.x ) + 0.375f * xStretch, + Math.max( vecStart.y, vecEnd.y ) + 0.375f * yStretch, + Math.max( vecStart.z, vecEnd.z ) + 0.375f * zStretch ); Entity closest = null; double closestDist = 99.0; - List list = world.getEntitiesByClass(Entity.class, bigBox, CAN_COLLIDE); - for (Entity entity : list) { + List list = world.getEntitiesByClass( Entity.class, bigBox, CAN_COLLIDE ); + for( Entity entity : list ) + { Box littleBox = entity.getBoundingBox(); - if (littleBox.contains(vecStart)) { + if( littleBox.contains( vecStart ) ) + { closest = entity; closestDist = 0.0f; continue; } - Vec3d littleBoxResult = littleBox.raycast(vecStart, vecEnd) - .orElse(null); - if (littleBoxResult != null) { - double dist = vecStart.distanceTo(littleBoxResult); - if (closest == null || dist <= closestDist) { + Vec3d littleBoxResult = littleBox.raycast( vecStart, vecEnd ) + .orElse( null ); + if( littleBoxResult != null ) + { + double dist = vecStart.distanceTo( littleBoxResult ); + if( closest == null || dist <= closestDist ) + { closest = entity; closestDist = dist; } - } else if (littleBox.intersects(bigBox)) { - if (closest == null) { + } + else if( littleBox.intersects( bigBox ) ) + { + if( closest == null ) + { closest = entity; closestDist = distance; } } } - if (closest != null && closestDist <= distance) { - Vec3d closestPos = vecStart.add(vecDir.x * closestDist, vecDir.y * closestDist, vecDir.z * closestDist); - return Pair.of(closest, closestPos); + if( closest != null && closestDist <= distance ) + { + Vec3d closestPos = vecStart.add( vecDir.x * closestDist, vecDir.y * closestDist, vecDir.z * closestDist ); + return Pair.of( closest, closestPos ); } return null; } - private static synchronized Entity getEntity(World world) { + private static synchronized Entity getEntity( World world ) + { // TODO: It'd be nice if we could avoid this. Maybe always use the turtle player (if it's available). - Entity entity = entityCache.get(world); - if (entity != null) { + Entity entity = entityCache.get( world ); + if( entity != null ) + { return entity; } - entity = new ItemEntity(EntityType.ITEM, world) { + entity = new ItemEntity( EntityType.ITEM, world ) + { @Nonnull @Override - public EntityDimensions getDimensions(@Nonnull EntityPose pose) { - return EntityDimensions.fixed(0, 0); + public EntityDimensions getDimensions( @Nonnull EntityPose pose ) + { + return EntityDimensions.fixed( 0, 0 ); } }; entity.noClip = true; entity.calculateDimensions(); - entityCache.put(world, entity); + entityCache.put( world, entity ); return entity; } - public static Vec3d getRayEnd(PlayerEntity player) { + public static Vec3d getRayEnd( PlayerEntity player ) + { double reach = 5; Vec3d look = player.getRotationVector(); - return getRayStart(player).add(look.x * reach, look.y * reach, look.z * reach); + return getRayStart( player ).add( look.x * reach, look.y * reach, look.z * reach ); } - public static Vec3d getRayStart(LivingEntity entity) { - return entity.getCameraPosVec(1); + public static Vec3d getRayStart( LivingEntity entity ) + { + return entity.getCameraPosVec( 1 ); } - public static void dropItemStack(@Nonnull ItemStack stack, World world, BlockPos pos) { - dropItemStack(stack, world, pos, null); + public static void dropItemStack( @Nonnull ItemStack stack, World world, BlockPos pos ) + { + dropItemStack( stack, world, pos, null ); } - public static void dropItemStack(@Nonnull ItemStack stack, World world, BlockPos pos, Direction direction) { + public static void dropItemStack( @Nonnull ItemStack stack, World world, BlockPos pos, Direction direction ) + { double xDir; double yDir; double zDir; - if (direction != null) { + if( direction != null ) + { xDir = direction.getOffsetX(); yDir = direction.getOffsetY(); zDir = direction.getOffsetZ(); - } else { + } + else + { xDir = 0.0; yDir = 0.0; zDir = 0.0; @@ -170,22 +190,24 @@ public final class WorldUtil { double xPos = pos.getX() + 0.5 + xDir * 0.4; double yPos = pos.getY() + 0.5 + yDir * 0.4; double zPos = pos.getZ() + 0.5 + zDir * 0.4; - dropItemStack(stack, world, new Vec3d(xPos, yPos, zPos), xDir, yDir, zDir); + dropItemStack( stack, world, new Vec3d( xPos, yPos, zPos ), xDir, yDir, zDir ); } - public static void dropItemStack(@Nonnull ItemStack stack, World world, Vec3d pos, double xDir, double yDir, double zDir) { - ItemEntity item = new ItemEntity(world, pos.x, pos.y, pos.z, stack.copy()); - item.setVelocity(xDir * 0.7 + world.getRandom() - .nextFloat() * 0.2 - 0.1, - yDir * 0.7 + world.getRandom() - .nextFloat() * 0.2 - 0.1, - zDir * 0.7 + world.getRandom() - .nextFloat() * 0.2 - 0.1); + public static void dropItemStack( @Nonnull ItemStack stack, World world, Vec3d pos, double xDir, double yDir, double zDir ) + { + ItemEntity item = new ItemEntity( world, pos.x, pos.y, pos.z, stack.copy() ); + item.setVelocity( xDir * 0.7 + world.getRandom() + .nextFloat() * 0.2 - 0.1, + yDir * 0.7 + world.getRandom() + .nextFloat() * 0.2 - 0.1, + zDir * 0.7 + world.getRandom() + .nextFloat() * 0.2 - 0.1 ); item.setToDefaultPickupDelay(); - world.spawnEntity(item); + world.spawnEntity( item ); } - public static void dropItemStack(@Nonnull ItemStack stack, World world, Vec3d pos) { - dropItemStack(stack, world, pos, 0.0, 0.0, 0.0); + public static void dropItemStack( @Nonnull ItemStack stack, World world, Vec3d pos ) + { + dropItemStack( stack, world, pos, 0.0, 0.0, 0.0 ); } } diff --git a/src/main/java/dan200/computercraft/shared/wired/InvariantChecker.java b/src/main/java/dan200/computercraft/shared/wired/InvariantChecker.java index 2dc36f67e..ab790e922 100644 --- a/src/main/java/dan200/computercraft/shared/wired/InvariantChecker.java +++ b/src/main/java/dan200/computercraft/shared/wired/InvariantChecker.java @@ -13,39 +13,49 @@ import dan200.computercraft.ComputerCraft; * * This adds substantial overhead to network modification, and so should only be enabled in a development environment. */ -public final class InvariantChecker { +public final class InvariantChecker +{ private static final boolean ENABLED = false; private InvariantChecker() {} - public static void checkNetwork(WiredNetwork network) { - if (!ENABLED) { + public static void checkNetwork( WiredNetwork network ) + { + if( !ENABLED ) + { return; } - for (WiredNode node : network.nodes) { - checkNode(node); + for( WiredNode node : network.nodes ) + { + checkNode( node ); } } - public static void checkNode(WiredNode node) { - if (!ENABLED) { + public static void checkNode( WiredNode node ) + { + if( !ENABLED ) + { return; } WiredNetwork network = node.network; - if (network == null) { - ComputerCraft.log.error("Node's network is null", new Exception()); + if( network == null ) + { + ComputerCraft.log.error( "Node's network is null", new Exception() ); return; } - if (network.nodes == null || !network.nodes.contains(node)) { - ComputerCraft.log.error("Node's network does not contain node", new Exception()); + if( network.nodes == null || !network.nodes.contains( node ) ) + { + ComputerCraft.log.error( "Node's network does not contain node", new Exception() ); } - for (WiredNode neighbour : node.neighbours) { - if (!neighbour.neighbours.contains(node)) { - ComputerCraft.log.error("Neighbour is missing node", new Exception()); + for( WiredNode neighbour : node.neighbours ) + { + if( !neighbour.neighbours.contains( node ) ) + { + ComputerCraft.log.error( "Neighbour is missing node", new Exception() ); } } } diff --git a/src/main/java/dan200/computercraft/shared/wired/WiredNetwork.java b/src/main/java/dan200/computercraft/shared/wired/WiredNetwork.java index 32375a800..9dd28fa52 100644 --- a/src/main/java/dan200/computercraft/shared/wired/WiredNetwork.java +++ b/src/main/java/dan200/computercraft/shared/wired/WiredNetwork.java @@ -6,197 +6,219 @@ package dan200.computercraft.shared.wired; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Queue; -import java.util.TreeSet; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import javax.annotation.Nonnull; - import com.google.common.collect.ImmutableMap; import dan200.computercraft.api.network.Packet; import dan200.computercraft.api.network.wired.IWiredNetwork; import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.peripheral.IPeripheral; - import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public final class WiredNetwork implements IWiredNetwork { +import javax.annotation.Nonnull; +import java.util.*; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public final class WiredNetwork implements IWiredNetwork +{ final ReadWriteLock lock = new ReentrantReadWriteLock(); HashSet nodes; private HashMap peripherals = new HashMap<>(); - WiredNetwork(WiredNode node) { - this.nodes = new HashSet<>(1); - this.nodes.add(node); + WiredNetwork( WiredNode node ) + { + this.nodes = new HashSet<>( 1 ); + this.nodes.add( node ); } - private WiredNetwork(HashSet nodes) { + private WiredNetwork( HashSet nodes ) + { this.nodes = nodes; } - static void transmitPacket(WiredNode start, Packet packet, double range, boolean interdimensional) { + static void transmitPacket( WiredNode start, Packet packet, double range, boolean interdimensional ) + { Map points = new HashMap<>(); TreeSet transmitTo = new TreeSet<>(); { TransmitPoint startEntry = start.element.getWorld() != packet.getSender() - .getWorld() ? new TransmitPoint(start, - Double.POSITIVE_INFINITY, - true) : new TransmitPoint(start, - start.element.getPosition() - .distanceTo( - packet.getSender() - .getPosition()), - false); - points.put(start, startEntry); - transmitTo.add(startEntry); + .getWorld() ? new TransmitPoint( start, + Double.POSITIVE_INFINITY, + true ) : new TransmitPoint( start, + start.element.getPosition() + .distanceTo( + packet.getSender() + .getPosition() ), + false ); + points.put( start, startEntry ); + transmitTo.add( startEntry ); } { TransmitPoint point; - while ((point = transmitTo.pollFirst()) != null) { + while( (point = transmitTo.pollFirst()) != null ) + { World world = point.node.element.getWorld(); Vec3d position = point.node.element.getPosition(); - for (WiredNode neighbour : point.node.neighbours) { - TransmitPoint neighbourPoint = points.get(neighbour); + for( WiredNode neighbour : point.node.neighbours ) + { + TransmitPoint neighbourPoint = points.get( neighbour ); boolean newInterdimensional; double newDistance; - if (world != neighbour.element.getWorld()) { + if( world != neighbour.element.getWorld() ) + { newInterdimensional = true; newDistance = Double.POSITIVE_INFINITY; - } else { + } + else + { newInterdimensional = false; - newDistance = point.distance + position.distanceTo(neighbour.element.getPosition()); + newDistance = point.distance + position.distanceTo( neighbour.element.getPosition() ); } - if (neighbourPoint == null) { - TransmitPoint nextPoint = new TransmitPoint(neighbour, newDistance, newInterdimensional); - points.put(neighbour, nextPoint); - transmitTo.add(nextPoint); - } else if (newDistance < neighbourPoint.distance) { - transmitTo.remove(neighbourPoint); + if( neighbourPoint == null ) + { + TransmitPoint nextPoint = new TransmitPoint( neighbour, newDistance, newInterdimensional ); + points.put( neighbour, nextPoint ); + transmitTo.add( nextPoint ); + } + else if( newDistance < neighbourPoint.distance ) + { + transmitTo.remove( neighbourPoint ); neighbourPoint.distance = newDistance; neighbourPoint.interdimensional = newInterdimensional; - transmitTo.add(neighbourPoint); + transmitTo.add( neighbourPoint ); } } } } - for (TransmitPoint point : points.values()) { - point.node.tryTransmit(packet, point.distance, point.interdimensional, range, interdimensional); + for( TransmitPoint point : points.values() ) + { + point.node.tryTransmit( packet, point.distance, point.interdimensional, range, interdimensional ); } } @Override - public boolean connect(@Nonnull IWiredNode nodeU, @Nonnull IWiredNode nodeV) { - WiredNode wiredU = checkNode(nodeU); - WiredNode wiredV = checkNode(nodeV); - if (nodeU == nodeV) { - throw new IllegalArgumentException("Cannot add a connection to oneself."); + public boolean connect( @Nonnull IWiredNode nodeU, @Nonnull IWiredNode nodeV ) + { + WiredNode wiredU = checkNode( nodeU ); + WiredNode wiredV = checkNode( nodeV ); + if( nodeU == nodeV ) + { + throw new IllegalArgumentException( "Cannot add a connection to oneself." ); } this.lock.writeLock() - .lock(); - try { - if (this.nodes == null) { - throw new IllegalStateException("Cannot add a connection to an empty network."); + .lock(); + try + { + if( this.nodes == null ) + { + throw new IllegalStateException( "Cannot add a connection to an empty network." ); } boolean hasU = wiredU.network == this; boolean hasV = wiredV.network == this; - if (!hasU && !hasV) { - throw new IllegalArgumentException("Neither node is in the network."); + if( !hasU && !hasV ) + { + throw new IllegalArgumentException( "Neither node is in the network." ); } // We're going to assimilate a node. Copy across all edges and vertices. - if (!hasU || !hasV) { + if( !hasU || !hasV ) + { WiredNetwork other = hasU ? wiredV.network : wiredU.network; other.lock.writeLock() - .lock(); - try { + .lock(); + try + { // Cache several properties for iterating over later Map otherPeripherals = other.peripherals; - Map thisPeripherals = otherPeripherals.isEmpty() ? this.peripherals : new HashMap<>(this.peripherals); + Map thisPeripherals = otherPeripherals.isEmpty() ? this.peripherals : new HashMap<>( this.peripherals ); - Collection thisNodes = otherPeripherals.isEmpty() ? this.nodes : new ArrayList<>(this.nodes); + Collection thisNodes = otherPeripherals.isEmpty() ? this.nodes : new ArrayList<>( this.nodes ); Collection otherNodes = other.nodes; // Move all nodes across into this network, destroying the original nodes. - this.nodes.addAll(otherNodes); - for (WiredNode node : otherNodes) { + this.nodes.addAll( otherNodes ); + for( WiredNode node : otherNodes ) + { node.network = this; } other.nodes = null; // Move all peripherals across, other.peripherals = null; - this.peripherals.putAll(otherPeripherals); + this.peripherals.putAll( otherPeripherals ); - if (!thisPeripherals.isEmpty()) { - WiredNetworkChange.added(thisPeripherals) - .broadcast(otherNodes); + if( !thisPeripherals.isEmpty() ) + { + WiredNetworkChange.added( thisPeripherals ) + .broadcast( otherNodes ); } - if (!otherPeripherals.isEmpty()) { - WiredNetworkChange.added(otherPeripherals) - .broadcast(thisNodes); + if( !otherPeripherals.isEmpty() ) + { + WiredNetworkChange.added( otherPeripherals ) + .broadcast( thisNodes ); } - } finally { + } + finally + { other.lock.writeLock() - .unlock(); + .unlock(); } } - boolean added = wiredU.neighbours.add(wiredV); - if (added) { - wiredV.neighbours.add(wiredU); + boolean added = wiredU.neighbours.add( wiredV ); + if( added ) + { + wiredV.neighbours.add( wiredU ); } - InvariantChecker.checkNetwork(this); - InvariantChecker.checkNode(wiredU); - InvariantChecker.checkNode(wiredV); + InvariantChecker.checkNetwork( this ); + InvariantChecker.checkNode( wiredU ); + InvariantChecker.checkNode( wiredV ); return added; - } finally { + } + finally + { this.lock.writeLock() - .unlock(); + .unlock(); } } @Override - public boolean disconnect(@Nonnull IWiredNode nodeU, @Nonnull IWiredNode nodeV) { - WiredNode wiredU = checkNode(nodeU); - WiredNode wiredV = checkNode(nodeV); - if (nodeU == nodeV) { - throw new IllegalArgumentException("Cannot remove a connection to oneself."); + public boolean disconnect( @Nonnull IWiredNode nodeU, @Nonnull IWiredNode nodeV ) + { + WiredNode wiredU = checkNode( nodeU ); + WiredNode wiredV = checkNode( nodeV ); + if( nodeU == nodeV ) + { + throw new IllegalArgumentException( "Cannot remove a connection to oneself." ); } this.lock.writeLock() - .lock(); - try { + .lock(); + try + { boolean hasU = wiredU.network == this; boolean hasV = wiredV.network == this; - if (!hasU || !hasV) { - throw new IllegalArgumentException("One node is not in the network."); + if( !hasU || !hasV ) + { + throw new IllegalArgumentException( "One node is not in the network." ); } // If there was no connection to remove then split. - if (!wiredU.neighbours.remove(wiredV)) { + if( !wiredU.neighbours.remove( wiredV ) ) + { return false; } - wiredV.neighbours.remove(wiredU); + wiredV.neighbours.remove( wiredU ); // Determine if there is still some connection from u to v. // Note this is an inlining of reachableNodes which short-circuits @@ -204,163 +226,193 @@ public final class WiredNetwork implements IWiredNetwork { Queue enqueued = new ArrayDeque<>(); HashSet reachableU = new HashSet<>(); - reachableU.add(wiredU); - enqueued.add(wiredU); + reachableU.add( wiredU ); + enqueued.add( wiredU ); - while (!enqueued.isEmpty()) { + while( !enqueued.isEmpty() ) + { WiredNode node = enqueued.remove(); - for (WiredNode neighbour : node.neighbours) { + for( WiredNode neighbour : node.neighbours ) + { // If we can reach wiredV from wiredU then abort. - if (neighbour == wiredV) { + if( neighbour == wiredV ) + { return true; } // Otherwise attempt to enqueue this neighbour as well. - if (reachableU.add(neighbour)) { - enqueued.add(neighbour); + if( reachableU.add( neighbour ) ) + { + enqueued.add( neighbour ); } } } // Create a new network with all U-reachable nodes/edges and remove them // from the existing graph. - WiredNetwork networkU = new WiredNetwork(reachableU); + WiredNetwork networkU = new WiredNetwork( reachableU ); networkU.lock.writeLock() - .lock(); - try { + .lock(); + try + { // Remove nodes from this network - this.nodes.removeAll(reachableU); + this.nodes.removeAll( reachableU ); // Set network and transfer peripherals - for (WiredNode node : reachableU) { + for( WiredNode node : reachableU ) + { node.network = networkU; - networkU.peripherals.putAll(node.peripherals); + networkU.peripherals.putAll( node.peripherals ); this.peripherals.keySet() - .removeAll(node.peripherals.keySet()); + .removeAll( node.peripherals.keySet() ); } // Broadcast changes - if (!this.peripherals.isEmpty()) { - WiredNetworkChange.removed(this.peripherals) - .broadcast(networkU.nodes); + if( !this.peripherals.isEmpty() ) + { + WiredNetworkChange.removed( this.peripherals ) + .broadcast( networkU.nodes ); } - if (!networkU.peripherals.isEmpty()) { - WiredNetworkChange.removed(networkU.peripherals) - .broadcast(this.nodes); + if( !networkU.peripherals.isEmpty() ) + { + WiredNetworkChange.removed( networkU.peripherals ) + .broadcast( this.nodes ); } - InvariantChecker.checkNetwork(this); - InvariantChecker.checkNetwork(networkU); - InvariantChecker.checkNode(wiredU); - InvariantChecker.checkNode(wiredV); + InvariantChecker.checkNetwork( this ); + InvariantChecker.checkNetwork( networkU ); + InvariantChecker.checkNode( wiredU ); + InvariantChecker.checkNode( wiredV ); return true; - } finally { - networkU.lock.writeLock() - .unlock(); } - } finally { + finally + { + networkU.lock.writeLock() + .unlock(); + } + } + finally + { this.lock.writeLock() - .unlock(); + .unlock(); } } @Override - public boolean remove(@Nonnull IWiredNode node) { - WiredNode wired = checkNode(node); + public boolean remove( @Nonnull IWiredNode node ) + { + WiredNode wired = checkNode( node ); this.lock.writeLock() - .lock(); - try { + .lock(); + try + { // If we're the empty graph then just abort: nodes must have _some_ network. - if (this.nodes == null) { + if( this.nodes == null ) + { return false; } - if (this.nodes.size() <= 1) { + if( this.nodes.size() <= 1 ) + { return false; } - if (wired.network != this) { + if( wired.network != this ) + { return false; } HashSet neighbours = wired.neighbours; // Remove this node and move into a separate network. - this.nodes.remove(wired); - for (WiredNode neighbour : neighbours) { - neighbour.neighbours.remove(wired); + this.nodes.remove( wired ); + for( WiredNode neighbour : neighbours ) + { + neighbour.neighbours.remove( wired ); } - WiredNetwork wiredNetwork = new WiredNetwork(wired); + WiredNetwork wiredNetwork = new WiredNetwork( wired ); // If we're a leaf node in the graph (only one neighbour) then we don't need to // check for network splitting - if (neighbours.size() == 1) { + if( neighbours.size() == 1 ) + { // Broadcast our simple peripheral changes - this.removeSingleNode(wired, wiredNetwork); - InvariantChecker.checkNode(wired); - InvariantChecker.checkNetwork(wiredNetwork); + this.removeSingleNode( wired, wiredNetwork ); + InvariantChecker.checkNode( wired ); + InvariantChecker.checkNetwork( wiredNetwork ); return true; } - HashSet reachable = reachableNodes(neighbours.iterator() - .next()); + HashSet reachable = reachableNodes( neighbours.iterator() + .next() ); // If all nodes are reachable then exit. - if (reachable.size() == this.nodes.size()) { + if( reachable.size() == this.nodes.size() ) + { // Broadcast our simple peripheral changes - this.removeSingleNode(wired, wiredNetwork); - InvariantChecker.checkNode(wired); - InvariantChecker.checkNetwork(wiredNetwork); + this.removeSingleNode( wired, wiredNetwork ); + InvariantChecker.checkNode( wired ); + InvariantChecker.checkNetwork( wiredNetwork ); return true; } // A split may cause 2..neighbours.size() separate networks, so we // iterate through our neighbour list, generating child networks. - neighbours.removeAll(reachable); - ArrayList maximals = new ArrayList<>(neighbours.size() + 1); - maximals.add(wiredNetwork); - maximals.add(new WiredNetwork(reachable)); + neighbours.removeAll( reachable ); + ArrayList maximals = new ArrayList<>( neighbours.size() + 1 ); + maximals.add( wiredNetwork ); + maximals.add( new WiredNetwork( reachable ) ); - while (!neighbours.isEmpty()) { - reachable = reachableNodes(neighbours.iterator() - .next()); - neighbours.removeAll(reachable); - maximals.add(new WiredNetwork(reachable)); + while( !neighbours.isEmpty() ) + { + reachable = reachableNodes( neighbours.iterator() + .next() ); + neighbours.removeAll( reachable ); + maximals.add( new WiredNetwork( reachable ) ); } - for (WiredNetwork network : maximals) { + for( WiredNetwork network : maximals ) + { network.lock.writeLock() - .lock(); + .lock(); } - try { + try + { // We special case the original node: detaching all peripherals when needed. wired.network = wiredNetwork; wired.peripherals = Collections.emptyMap(); // Ensure every network is finalised - for (WiredNetwork network : maximals) { - for (WiredNode child : network.nodes) { + for( WiredNetwork network : maximals ) + { + for( WiredNode child : network.nodes ) + { child.network = network; - network.peripherals.putAll(child.peripherals); + network.peripherals.putAll( child.peripherals ); } } - for (WiredNetwork network : maximals) { - InvariantChecker.checkNetwork(network); + for( WiredNetwork network : maximals ) + { + InvariantChecker.checkNetwork( network ); } - InvariantChecker.checkNode(wired); + InvariantChecker.checkNode( wired ); // Then broadcast network changes once all nodes are finalised - for (WiredNetwork network : maximals) { - WiredNetworkChange.changeOf(this.peripherals, network.peripherals) - .broadcast(network.nodes); + for( WiredNetwork network : maximals ) + { + WiredNetworkChange.changeOf( this.peripherals, network.peripherals ) + .broadcast( network.nodes ); } - } finally { - for (WiredNetwork network : maximals) { + } + finally + { + for( WiredNetwork network : maximals ) + { network.lock.writeLock() - .unlock(); + .unlock(); } } @@ -368,53 +420,63 @@ public final class WiredNetwork implements IWiredNetwork { this.peripherals.clear(); return true; - } finally { + } + finally + { this.lock.writeLock() - .unlock(); + .unlock(); } } @Override - public void updatePeripherals(@Nonnull IWiredNode node, @Nonnull Map newPeripherals) { - WiredNode wired = checkNode(node); - Objects.requireNonNull(this.peripherals, "peripherals cannot be null"); + public void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map newPeripherals ) + { + WiredNode wired = checkNode( node ); + Objects.requireNonNull( this.peripherals, "peripherals cannot be null" ); this.lock.writeLock() - .lock(); - try { - if (wired.network != this) { - throw new IllegalStateException("Node is not on this network"); + .lock(); + try + { + if( wired.network != this ) + { + throw new IllegalStateException( "Node is not on this network" ); } Map oldPeripherals = wired.peripherals; - WiredNetworkChange change = WiredNetworkChange.changeOf(oldPeripherals, newPeripherals); - if (change.isEmpty()) { + WiredNetworkChange change = WiredNetworkChange.changeOf( oldPeripherals, newPeripherals ); + if( change.isEmpty() ) + { return; } - wired.peripherals = ImmutableMap.copyOf(newPeripherals); + wired.peripherals = ImmutableMap.copyOf( newPeripherals ); // Detach the old peripherals then remove them. this.peripherals.keySet() - .removeAll(change.peripheralsRemoved() - .keySet()); + .removeAll( change.peripheralsRemoved() + .keySet() ); // Add the new peripherals and attach them - this.peripherals.putAll(change.peripheralsAdded()); + this.peripherals.putAll( change.peripheralsAdded() ); - change.broadcast(this.nodes); - } finally { + change.broadcast( this.nodes ); + } + finally + { this.lock.writeLock() - .unlock(); + .unlock(); } } - private void removeSingleNode(WiredNode wired, WiredNetwork wiredNetwork) { + private void removeSingleNode( WiredNode wired, WiredNetwork wiredNetwork ) + { wiredNetwork.lock.writeLock() - .lock(); - try { + .lock(); + try + { // Cache all the old nodes. - Map wiredPeripherals = new HashMap<>(wired.peripherals); + Map wiredPeripherals = new HashMap<>( wired.peripherals ); // Setup the new node's network // Detach the old peripherals then remove them from the old network @@ -423,38 +485,46 @@ public final class WiredNetwork implements IWiredNetwork { wired.peripherals = Collections.emptyMap(); // Broadcast the change - if (!this.peripherals.isEmpty()) { - WiredNetworkChange.removed(this.peripherals) - .broadcast(wired); + if( !this.peripherals.isEmpty() ) + { + WiredNetworkChange.removed( this.peripherals ) + .broadcast( wired ); } // Now remove all peripherals from this network and broadcast the change. this.peripherals.keySet() - .removeAll(wiredPeripherals.keySet()); - if (!wiredPeripherals.isEmpty()) { - WiredNetworkChange.removed(wiredPeripherals) - .broadcast(this.nodes); + .removeAll( wiredPeripherals.keySet() ); + if( !wiredPeripherals.isEmpty() ) + { + WiredNetworkChange.removed( wiredPeripherals ) + .broadcast( this.nodes ); } - } finally { + } + finally + { wiredNetwork.lock.writeLock() - .unlock(); + .unlock(); } } - private static HashSet reachableNodes(WiredNode start) { + private static HashSet reachableNodes( WiredNode start ) + { Queue enqueued = new ArrayDeque<>(); HashSet reachable = new HashSet<>(); - reachable.add(start); - enqueued.add(start); + reachable.add( start ); + enqueued.add( start ); WiredNode node; - while ((node = enqueued.poll()) != null) { - for (WiredNode neighbour : node.neighbours) { + while( (node = enqueued.poll()) != null ) + { + for( WiredNode neighbour : node.neighbours ) + { // Otherwise attempt to enqueue this neighbour as well. - if (reachable.add(neighbour)) { - enqueued.add(neighbour); + if( reachable.add( neighbour ) ) + { + enqueued.add( neighbour ); } } } @@ -462,29 +532,36 @@ public final class WiredNetwork implements IWiredNetwork { return reachable; } - private static WiredNode checkNode(IWiredNode node) { - if (node instanceof WiredNode) { + private static WiredNode checkNode( IWiredNode node ) + { + if( node instanceof WiredNode ) + { return (WiredNode) node; - } else { - throw new IllegalArgumentException("Unknown implementation of IWiredNode: " + node); + } + else + { + throw new IllegalArgumentException( "Unknown implementation of IWiredNode: " + node ); } } - private static class TransmitPoint implements Comparable { + private static class TransmitPoint implements Comparable + { final WiredNode node; double distance; boolean interdimensional; - TransmitPoint(WiredNode node, double distance, boolean interdimensional) { + TransmitPoint( WiredNode node, double distance, boolean interdimensional ) + { this.node = node; this.distance = distance; this.interdimensional = interdimensional; } @Override - public int compareTo(@Nonnull TransmitPoint o) { + public int compareTo( @Nonnull TransmitPoint o ) + { // Objects with the same distance are not the same object, so we must add an additional layer of ordering. - return this.distance == o.distance ? Integer.compare(this.node.hashCode(), o.node.hashCode()) : Double.compare(this.distance, o.distance); + return this.distance == o.distance ? Integer.compare( this.node.hashCode(), o.node.hashCode() ) : Double.compare( this.distance, o.distance ); } } } diff --git a/src/main/java/dan200/computercraft/shared/wired/WiredNetworkChange.java b/src/main/java/dan200/computercraft/shared/wired/WiredNetworkChange.java index fac45ccf7..cdaabfc32 100644 --- a/src/main/java/dan200/computercraft/shared/wired/WiredNetworkChange.java +++ b/src/main/java/dan200/computercraft/shared/wired/WiredNetworkChange.java @@ -6,96 +6,121 @@ package dan200.computercraft.shared.wired; +import dan200.computercraft.api.network.wired.IWiredNetworkChange; +import dan200.computercraft.api.peripheral.IPeripheral; + +import javax.annotation.Nonnull; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nonnull; - -import dan200.computercraft.api.network.wired.IWiredNetworkChange; -import dan200.computercraft.api.peripheral.IPeripheral; - -public final class WiredNetworkChange implements IWiredNetworkChange { - private static final WiredNetworkChange EMPTY = new WiredNetworkChange(Collections.emptyMap(), Collections.emptyMap()); +public final class WiredNetworkChange implements IWiredNetworkChange +{ + private static final WiredNetworkChange EMPTY = new WiredNetworkChange( Collections.emptyMap(), Collections.emptyMap() ); private final Map removed; private final Map added; - private WiredNetworkChange(Map removed, Map added) { + private WiredNetworkChange( Map removed, Map added ) + { this.removed = removed; this.added = added; } - public static WiredNetworkChange added(Map added) { - return added.isEmpty() ? EMPTY : new WiredNetworkChange(Collections.emptyMap(), Collections.unmodifiableMap(added)); + public static WiredNetworkChange added( Map added ) + { + return added.isEmpty() ? EMPTY : new WiredNetworkChange( Collections.emptyMap(), Collections.unmodifiableMap( added ) ); } - public static WiredNetworkChange removed(Map removed) { - return removed.isEmpty() ? EMPTY : new WiredNetworkChange(Collections.unmodifiableMap(removed), Collections.emptyMap()); + public static WiredNetworkChange removed( Map removed ) + { + return removed.isEmpty() ? EMPTY : new WiredNetworkChange( Collections.unmodifiableMap( removed ), Collections.emptyMap() ); } - public static WiredNetworkChange changeOf(Map oldPeripherals, Map newPeripherals) { + public static WiredNetworkChange changeOf( Map oldPeripherals, Map newPeripherals ) + { // Handle the trivial cases, where all peripherals have been added or removed. - if (oldPeripherals.isEmpty() && newPeripherals.isEmpty()) { + if( oldPeripherals.isEmpty() && newPeripherals.isEmpty() ) + { return EMPTY; - } else if (oldPeripherals.isEmpty()) { - return new WiredNetworkChange(Collections.emptyMap(), newPeripherals); - } else if (newPeripherals.isEmpty()) { - return new WiredNetworkChange(oldPeripherals, Collections.emptyMap()); + } + else if( oldPeripherals.isEmpty() ) + { + return new WiredNetworkChange( Collections.emptyMap(), newPeripherals ); + } + else if( newPeripherals.isEmpty() ) + { + return new WiredNetworkChange( oldPeripherals, Collections.emptyMap() ); } - Map added = new HashMap<>(newPeripherals); + Map added = new HashMap<>( newPeripherals ); Map removed = new HashMap<>(); - for (Map.Entry entry : oldPeripherals.entrySet()) { + for( Map.Entry entry : oldPeripherals.entrySet() ) + { String oldKey = entry.getKey(); IPeripheral oldValue = entry.getValue(); - if (newPeripherals.containsKey(oldKey)) { - IPeripheral rightValue = added.get(oldKey); - if (oldValue.equals(rightValue)) { - added.remove(oldKey); - } else { - removed.put(oldKey, oldValue); + if( newPeripherals.containsKey( oldKey ) ) + { + IPeripheral rightValue = added.get( oldKey ); + if( oldValue.equals( rightValue ) ) + { + added.remove( oldKey ); } - } else { - removed.put(oldKey, oldValue); + else + { + removed.put( oldKey, oldValue ); + } + } + else + { + removed.put( oldKey, oldValue ); } } - return changed(removed, added); + return changed( removed, added ); } - public static WiredNetworkChange changed(Map removed, Map added) { - return new WiredNetworkChange(Collections.unmodifiableMap(removed), Collections.unmodifiableMap(added)); + public static WiredNetworkChange changed( Map removed, Map added ) + { + return new WiredNetworkChange( Collections.unmodifiableMap( removed ), Collections.unmodifiableMap( added ) ); } @Nonnull @Override - public Map peripheralsRemoved() { + public Map peripheralsRemoved() + { return this.removed; } @Nonnull @Override - public Map peripheralsAdded() { + public Map peripheralsAdded() + { return this.added; } - void broadcast(Iterable nodes) { - if (!this.isEmpty()) { - for (WiredNode node : nodes) { - node.element.networkChanged(this); + void broadcast( Iterable nodes ) + { + if( !this.isEmpty() ) + { + for( WiredNode node : nodes ) + { + node.element.networkChanged( this ); } } } - public boolean isEmpty() { + public boolean isEmpty() + { return this.added.isEmpty() && this.removed.isEmpty(); } - void broadcast(WiredNode node) { - if (!this.isEmpty()) { - node.element.networkChanged(this); + void broadcast( WiredNode node ) + { + if( !this.isEmpty() ) + { + node.element.networkChanged( this ); } } } diff --git a/src/main/java/dan200/computercraft/shared/wired/WiredNode.java b/src/main/java/dan200/computercraft/shared/wired/WiredNode.java index 8d1c55241..fdb5048f0 100644 --- a/src/main/java/dan200/computercraft/shared/wired/WiredNode.java +++ b/src/main/java/dan200/computercraft/shared/wired/WiredNode.java @@ -6,15 +6,6 @@ package dan200.computercraft.shared.wired; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.locks.Lock; - -import javax.annotation.Nonnull; - import dan200.computercraft.api.network.IPacketReceiver; import dan200.computercraft.api.network.Packet; import dan200.computercraft.api.network.wired.IWiredElement; @@ -23,76 +14,100 @@ import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.network.wired.IWiredSender; import dan200.computercraft.api.peripheral.IPeripheral; -public final class WiredNode implements IWiredNode { +import javax.annotation.Nonnull; +import java.util.*; +import java.util.concurrent.locks.Lock; + +public final class WiredNode implements IWiredNode +{ final IWiredElement element; final HashSet neighbours = new HashSet<>(); Map peripherals = Collections.emptyMap(); volatile WiredNetwork network; private Set receivers; - public WiredNode(IWiredElement element) { + public WiredNode( IWiredElement element ) + { this.element = element; - this.network = new WiredNetwork(this); + this.network = new WiredNetwork( this ); } @Override - public synchronized void addReceiver(@Nonnull IPacketReceiver receiver) { - if (this.receivers == null) { + public synchronized void addReceiver( @Nonnull IPacketReceiver receiver ) + { + if( this.receivers == null ) + { this.receivers = new HashSet<>(); } - this.receivers.add(receiver); + this.receivers.add( receiver ); } @Override - public synchronized void removeReceiver(@Nonnull IPacketReceiver receiver) { - if (this.receivers != null) { - this.receivers.remove(receiver); + public synchronized void removeReceiver( @Nonnull IPacketReceiver receiver ) + { + if( this.receivers != null ) + { + this.receivers.remove( receiver ); } } @Override - public boolean isWireless() { + public boolean isWireless() + { return false; } @Override - public void transmitSameDimension(@Nonnull Packet packet, double range) { - Objects.requireNonNull(packet, "packet cannot be null"); - if (!(packet.getSender() instanceof IWiredSender) || ((IWiredSender) packet.getSender()).getNode() != this) { - throw new IllegalArgumentException("Sender is not in the network"); + public void transmitSameDimension( @Nonnull Packet packet, double range ) + { + Objects.requireNonNull( packet, "packet cannot be null" ); + if( !(packet.getSender() instanceof IWiredSender) || ((IWiredSender) packet.getSender()).getNode() != this ) + { + throw new IllegalArgumentException( "Sender is not in the network" ); } this.acquireReadLock(); - try { - WiredNetwork.transmitPacket(this, packet, range, false); - } finally { + try + { + WiredNetwork.transmitPacket( this, packet, range, false ); + } + finally + { this.network.lock.readLock() - .unlock(); + .unlock(); } } @Override - public void transmitInterdimensional(@Nonnull Packet packet) { - Objects.requireNonNull(packet, "packet cannot be null"); - if (!(packet.getSender() instanceof IWiredSender) || ((IWiredSender) packet.getSender()).getNode() != this) { - throw new IllegalArgumentException("Sender is not in the network"); + public void transmitInterdimensional( @Nonnull Packet packet ) + { + Objects.requireNonNull( packet, "packet cannot be null" ); + if( !(packet.getSender() instanceof IWiredSender) || ((IWiredSender) packet.getSender()).getNode() != this ) + { + throw new IllegalArgumentException( "Sender is not in the network" ); } this.acquireReadLock(); - try { - WiredNetwork.transmitPacket(this, packet, 0, true); - } finally { + try + { + WiredNetwork.transmitPacket( this, packet, 0, true ); + } + finally + { this.network.lock.readLock() - .unlock(); + .unlock(); } } - private void acquireReadLock() { + private void acquireReadLock() + { WiredNetwork currentNetwork = this.network; - while (true) { + while( true ) + { Lock lock = currentNetwork.lock.readLock(); lock.lock(); - if (currentNetwork == this.network) { + if( currentNetwork == this.network ) + { return; } @@ -101,22 +116,30 @@ public final class WiredNode implements IWiredNode { } } - synchronized void tryTransmit(Packet packet, double packetDistance, boolean packetInterdimensional, double range, boolean interdimensional) { - if (this.receivers == null) { + synchronized void tryTransmit( Packet packet, double packetDistance, boolean packetInterdimensional, double range, boolean interdimensional ) + { + if( this.receivers == null ) + { return; } - for (IPacketReceiver receiver : this.receivers) { - if (!packetInterdimensional) { - double receiveRange = Math.max(range, receiver.getRange()); // Ensure range is symmetrical - if (interdimensional || receiver.isInterdimensional() || packetDistance < receiveRange) { - receiver.receiveSameDimension(packet, - packetDistance + this.element.getPosition() - .distanceTo(receiver.getPosition())); + for( IPacketReceiver receiver : this.receivers ) + { + if( !packetInterdimensional ) + { + double receiveRange = Math.max( range, receiver.getRange() ); // Ensure range is symmetrical + if( interdimensional || receiver.isInterdimensional() || packetDistance < receiveRange ) + { + receiver.receiveSameDimension( packet, + packetDistance + this.element.getPosition() + .distanceTo( receiver.getPosition() ) ); } - } else { - if (interdimensional || receiver.isInterdimensional()) { - receiver.receiveDifferentDimension(packet); + } + else + { + if( interdimensional || receiver.isInterdimensional() ) + { + receiver.receiveDifferentDimension( packet ); } } } @@ -124,19 +147,22 @@ public final class WiredNode implements IWiredNode { @Nonnull @Override - public IWiredElement getElement() { + public IWiredElement getElement() + { return this.element; } @Nonnull @Override - public IWiredNetwork getNetwork() { + public IWiredNetwork getNetwork() + { return this.network; } @Override - public String toString() { + public String toString() + { return "WiredNode{@" + this.element.getPosition() + " (" + this.element.getClass() - .getSimpleName() + ")}"; + .getSimpleName() + ")}"; } } From a198a5241dbaa94bb483b3ece8100483f329fca4 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 9 Jun 2021 07:55:17 +0100 Subject: [PATCH 4/8] Use CC:T's version of dan200.computercraft.core --- .../computercraft/core/apis/ApiFactories.java | 7 +- .../core/apis/ComputerAccess.java | 69 +- .../dan200/computercraft/core/apis/FSAPI.java | 98 +-- .../computercraft/core/apis/HTTPAPI.java | 14 +- .../core/apis/IAPIEnvironment.java | 17 +- .../computercraft/core/apis/LuaDateTime.java | 79 +- .../dan200/computercraft/core/apis/OSAPI.java | 596 ++++++------- .../core/apis/PeripheralAPI.java | 500 +++++------ .../computercraft/core/apis/RedstoneAPI.java | 97 +-- .../computercraft/core/apis/TableHelper.java | 102 ++- .../computercraft/core/apis/TermAPI.java | 17 +- .../computercraft/core/apis/TermMethods.java | 220 +++-- .../core/apis/http/CheckUrl.java | 31 +- .../core/apis/http/HTTPRequestException.java | 1 - .../core/apis/http/NetworkUtils.java | 136 +-- .../core/apis/http/Resource.java | 131 ++- .../core/apis/http/ResourceGroup.java | 34 +- .../core/apis/http/ResourceQueue.java | 29 +- .../core/apis/http/options/Action.java | 5 +- .../core/apis/http/options/AddressRule.java | 35 +- .../apis/http/options/AddressRuleConfig.java | 9 +- .../apis/http/options/PartialOptions.java | 43 +- .../core/apis/http/request/HttpRequest.java | 188 ++--- .../apis/http/request/HttpRequestHandler.java | 4 +- .../apis/http/request/HttpResponseHandle.java | 40 +- .../core/apis/http/websocket/Websocket.java | 123 ++- .../apis/http/websocket/WebsocketHandle.java | 52 +- .../apis/http/websocket/WebsocketHandler.java | 92 +- .../core/asm/DeclaringClassLoader.java | 2 +- .../computercraft/core/asm/Generator.java | 166 ++-- .../computercraft/core/asm/IntCache.java | 26 +- .../computercraft/core/asm/LuaMethod.java | 13 +- .../computercraft/core/asm/NamedMethod.java | 6 +- .../computercraft/core/asm/ObjectSource.java | 18 +- .../core/asm/PeripheralMethod.java | 18 +- .../computercraft/core/asm/Reflect.java | 54 +- .../computercraft/core/asm/TaskCallback.java | 57 +- .../core/computer/ApiWrapper.java | 13 +- .../computercraft/core/computer/Computer.java | 133 ++- .../core/computer/ComputerExecutor.java | 725 ++++++++-------- .../core/computer/ComputerSide.java | 29 +- .../core/computer/ComputerSystem.java | 31 +- .../core/computer/ComputerThread.java | 327 +++----- .../core/computer/Environment.java | 259 +++--- .../core/computer/IComputerEnvironment.java | 1 - .../core/computer/MainThread.java | 74 +- .../core/computer/MainThreadExecutor.java | 188 ++--- .../core/computer/TimeoutState.java | 71 +- .../core/filesystem/ComboMount.java | 101 ++- .../core/filesystem/EmptyMount.java | 25 +- .../core/filesystem/FileMount.java | 786 ++++++++---------- .../core/filesystem/FileSystemException.java | 1 - .../filesystem/FileSystemWrapperMount.java | 134 ++- .../core/filesystem/JarMount.java | 198 ++--- .../core/filesystem/MountWrapper.java | 458 +++++----- .../core/filesystem/ResourceMount.java | 264 +++--- .../core/filesystem/SubMount.java | 49 +- .../computercraft/core/lua/BasicFunction.java | 6 +- .../core/lua/CobaltLuaMachine.java | 775 +++++++---------- .../computercraft/core/lua/ILuaMachine.java | 28 +- .../computercraft/core/lua/LuaContext.java | 69 ++ .../computercraft/core/lua/MachineResult.java | 7 +- .../core/lua/ResultInterpreterFunction.java | 55 +- .../core/lua/VarargArguments.java | 81 +- .../computercraft/core/terminal/Terminal.java | 436 +++++----- .../core/terminal/TextBuffer.java | 2 +- .../core/tracking/ComputerTracker.java | 107 +-- .../computercraft/core/tracking/Tracker.java | 5 +- .../computercraft/core/tracking/Tracking.java | 51 +- .../core/tracking/TrackingContext.java | 73 +- .../core/tracking/TrackingField.java | 62 +- .../computercraft/shared/util/Config.java | 421 +++++----- 72 files changed, 4106 insertions(+), 5068 deletions(-) create mode 100644 src/main/java/dan200/computercraft/core/lua/LuaContext.java diff --git a/src/main/java/dan200/computercraft/core/apis/ApiFactories.java b/src/main/java/dan200/computercraft/core/apis/ApiFactories.java index fc4b9eff7..0f801e865 100644 --- a/src/main/java/dan200/computercraft/core/apis/ApiFactories.java +++ b/src/main/java/dan200/computercraft/core/apis/ApiFactories.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.lua.ILuaAPIFactory; @@ -16,13 +15,13 @@ import java.util.Objects; public final class ApiFactories { - private static final Collection factories = new LinkedHashSet<>(); - private static final Collection factoriesView = Collections.unmodifiableCollection( factories ); - private ApiFactories() { } + private static final Collection factories = new LinkedHashSet<>(); + private static final Collection factoriesView = Collections.unmodifiableCollection( factories ); + public static synchronized void register( @Nonnull ILuaAPIFactory factory ) { Objects.requireNonNull( factory, "provider cannot be null" ); diff --git a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java index c71e9ec7b..39c4a2ff3 100644 --- a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java +++ b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.filesystem.IMount; @@ -20,22 +19,22 @@ import java.util.Set; public abstract class ComputerAccess implements IComputerAccess { - private final IAPIEnvironment m_environment; - private final Set m_mounts = new HashSet<>(); + private final IAPIEnvironment environment; + private final Set mounts = new HashSet<>(); protected ComputerAccess( IAPIEnvironment environment ) { - this.m_environment = environment; + this.environment = environment; } public void unmountAll() { - FileSystem fileSystem = this.m_environment.getFileSystem(); - for( String mount : this.m_mounts ) + FileSystem fileSystem = environment.getFileSystem(); + for( String mount : mounts ) { fileSystem.unmount( mount ); } - this.m_mounts.clear(); + mounts.clear(); } @Override @@ -47,15 +46,12 @@ public abstract class ComputerAccess implements IComputerAccess // Mount the location String location; - FileSystem fileSystem = this.m_environment.getFileSystem(); - if( fileSystem == null ) - { - throw new IllegalStateException( "File system has not been created" ); - } + FileSystem fileSystem = environment.getFileSystem(); + if( fileSystem == null ) throw new IllegalStateException( "File system has not been created" ); synchronized( fileSystem ) { - location = this.findFreeLocation( desiredLoc ); + location = findFreeLocation( desiredLoc ); if( location != null ) { try @@ -68,10 +64,7 @@ public abstract class ComputerAccess implements IComputerAccess } } - if( location != null ) - { - this.m_mounts.add( location ); - } + if( location != null ) mounts.add( location ); return location; } @@ -84,15 +77,12 @@ public abstract class ComputerAccess implements IComputerAccess // Mount the location String location; - FileSystem fileSystem = this.m_environment.getFileSystem(); - if( fileSystem == null ) - { - throw new IllegalStateException( "File system has not been created" ); - } + FileSystem fileSystem = environment.getFileSystem(); + if( fileSystem == null ) throw new IllegalStateException( "File system has not been created" ); synchronized( fileSystem ) { - location = this.findFreeLocation( desiredLoc ); + location = findFreeLocation( desiredLoc ); if( location != null ) { try @@ -105,59 +95,46 @@ public abstract class ComputerAccess implements IComputerAccess } } - if( location != null ) - { - this.m_mounts.add( location ); - } + if( location != null ) mounts.add( location ); return location; } @Override public void unmount( String location ) { - if( location == null ) - { - return; - } - if( !this.m_mounts.contains( location ) ) - { - throw new IllegalStateException( "You didn't mount this location" ); - } + if( location == null ) return; + if( !mounts.contains( location ) ) throw new IllegalStateException( "You didn't mount this location" ); - this.m_environment.getFileSystem() - .unmount( location ); - this.m_mounts.remove( location ); + environment.getFileSystem().unmount( location ); + mounts.remove( location ); } @Override public int getID() { - return this.m_environment.getComputerID(); + return environment.getComputerID(); } @Override public void queueEvent( @Nonnull String event, Object... arguments ) { Objects.requireNonNull( event, "event cannot be null" ); - this.m_environment.queueEvent( event, arguments ); + environment.queueEvent( event, arguments ); } @Nonnull @Override public IWorkMonitor getMainThreadMonitor() { - return this.m_environment.getMainThreadMonitor(); + return environment.getMainThreadMonitor(); } private String findFreeLocation( String desiredLoc ) { try { - FileSystem fileSystem = this.m_environment.getFileSystem(); - if( !fileSystem.exists( desiredLoc ) ) - { - return desiredLoc; - } + FileSystem fileSystem = environment.getFileSystem(); + if( !fileSystem.exists( desiredLoc ) ) return desiredLoc; // We used to check foo2, foo3, foo4, etc here but the disk drive does this itself now return null; diff --git a/src/main/java/dan200/computercraft/core/apis/FSAPI.java b/src/main/java/dan200/computercraft/core/apis/FSAPI.java index fa174c003..5cd6b9e2c 100644 --- a/src/main/java/dan200/computercraft/core/apis/FSAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/FSAPI.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.lua.IArguments; @@ -42,7 +41,7 @@ public class FSAPI implements ILuaAPI public FSAPI( IAPIEnvironment env ) { - this.environment = env; + environment = env; } @Override @@ -54,13 +53,13 @@ public class FSAPI implements ILuaAPI @Override public void startup() { - this.fileSystem = this.environment.getFileSystem(); + fileSystem = environment.getFileSystem(); } @Override public void shutdown() { - this.fileSystem = null; + fileSystem = null; } /** @@ -73,10 +72,10 @@ public class FSAPI implements ILuaAPI @LuaFunction public final String[] list( String path ) throws LuaException { - this.environment.addTrackingChange( TrackingField.FS_OPS ); + environment.addTrackingChange( TrackingField.FS_OPS ); try { - return this.fileSystem.list( path ); + return fileSystem.list( path ); } catch( FileSystemException e ) { @@ -86,7 +85,7 @@ public class FSAPI implements ILuaAPI /** * Combines several parts of a path into one full path, adding separators as - * needed + * needed. * * @param arguments The paths to combine. * @return The new path, with separators added between parts as needed. @@ -146,7 +145,7 @@ public class FSAPI implements ILuaAPI { try { - return this.fileSystem.getSize( path ); + return fileSystem.getSize( path ); } catch( FileSystemException e ) { @@ -165,7 +164,7 @@ public class FSAPI implements ILuaAPI { try { - return this.fileSystem.exists( path ); + return fileSystem.exists( path ); } catch( FileSystemException e ) { @@ -184,7 +183,7 @@ public class FSAPI implements ILuaAPI { try { - return this.fileSystem.isDir( path ); + return fileSystem.isDir( path ); } catch( FileSystemException e ) { @@ -203,7 +202,7 @@ public class FSAPI implements ILuaAPI { try { - return this.fileSystem.isReadOnly( path ); + return fileSystem.isReadOnly( path ); } catch( FileSystemException e ) { @@ -222,8 +221,8 @@ public class FSAPI implements ILuaAPI { try { - this.environment.addTrackingChange( TrackingField.FS_OPS ); - this.fileSystem.makeDir( path ); + environment.addTrackingChange( TrackingField.FS_OPS ); + fileSystem.makeDir( path ); } catch( FileSystemException e ) { @@ -245,8 +244,8 @@ public class FSAPI implements ILuaAPI { try { - this.environment.addTrackingChange( TrackingField.FS_OPS ); - this.fileSystem.move( path, dest ); + environment.addTrackingChange( TrackingField.FS_OPS ); + fileSystem.move( path, dest ); } catch( FileSystemException e ) { @@ -268,8 +267,8 @@ public class FSAPI implements ILuaAPI { try { - this.environment.addTrackingChange( TrackingField.FS_OPS ); - this.fileSystem.copy( path, dest ); + environment.addTrackingChange( TrackingField.FS_OPS ); + fileSystem.copy( path, dest ); } catch( FileSystemException e ) { @@ -280,7 +279,8 @@ public class FSAPI implements ILuaAPI /** * Deletes a file or directory. * - * If the path points to a directory, all of the enclosed files and subdirectories are also deleted. + * If the path points to a directory, all of the enclosed files and + * subdirectories are also deleted. * * @param path The path to the file or directory to delete. * @throws LuaException If the file or directory couldn't be deleted. @@ -290,8 +290,8 @@ public class FSAPI implements ILuaAPI { try { - this.environment.addTrackingChange( TrackingField.FS_OPS ); - this.fileSystem.delete( path ); + environment.addTrackingChange( TrackingField.FS_OPS ); + fileSystem.delete( path ); } catch( FileSystemException e ) { @@ -304,8 +304,10 @@ public class FSAPI implements ILuaAPI /** * Opens a file for reading or writing at a path. * - * The mode parameter can be {@code r} to read, {@code w} to write (deleting all contents), or {@code a} to append (keeping contents). If {@code b} is - * added to the end, the file will be opened in binary mode; otherwise, it's opened in text mode. + * The mode parameter can be {@code r} to read, {@code w} to write (deleting + * all contents), or {@code a} to append (keeping contents). If {@code b} is + * added to the end, the file will be opened in binary mode; otherwise, it's + * opened in text mode. * * @param path The path to the file to open. * @param mode The mode to open the file with. @@ -318,7 +320,7 @@ public class FSAPI implements ILuaAPI @LuaFunction public final Object[] open( String path, String mode ) throws LuaException { - this.environment.addTrackingChange( TrackingField.FS_OPS ); + environment.addTrackingChange( TrackingField.FS_OPS ); try { switch( mode ) @@ -326,37 +328,37 @@ public class FSAPI implements ILuaAPI case "r": { // Open the file for reading, then create a wrapper around the reader - FileSystemWrapper reader = this.fileSystem.openForRead( path, EncodedReadableHandle::openUtf8 ); + FileSystemWrapper reader = fileSystem.openForRead( path, EncodedReadableHandle::openUtf8 ); return new Object[] { new EncodedReadableHandle( reader.get(), reader ) }; } case "w": { // Open the file for writing, then create a wrapper around the writer - FileSystemWrapper writer = this.fileSystem.openForWrite( path, false, EncodedWritableHandle::openUtf8 ); + FileSystemWrapper writer = fileSystem.openForWrite( path, false, EncodedWritableHandle::openUtf8 ); return new Object[] { new EncodedWritableHandle( writer.get(), writer ) }; } case "a": { // Open the file for appending, then create a wrapper around the writer - FileSystemWrapper writer = this.fileSystem.openForWrite( path, true, EncodedWritableHandle::openUtf8 ); + FileSystemWrapper writer = fileSystem.openForWrite( path, true, EncodedWritableHandle::openUtf8 ); return new Object[] { new EncodedWritableHandle( writer.get(), writer ) }; } case "rb": { // Open the file for binary reading, then create a wrapper around the reader - FileSystemWrapper reader = this.fileSystem.openForRead( path, Function.identity() ); + FileSystemWrapper reader = fileSystem.openForRead( path, Function.identity() ); return new Object[] { BinaryReadableHandle.of( reader.get(), reader ) }; } case "wb": { // Open the file for binary writing, then create a wrapper around the writer - FileSystemWrapper writer = this.fileSystem.openForWrite( path, false, Function.identity() ); + FileSystemWrapper writer = fileSystem.openForWrite( path, false, Function.identity() ); return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) }; } case "ab": { // Open the file for binary appending, then create a wrapper around the reader - FileSystemWrapper writer = this.fileSystem.openForWrite( path, true, Function.identity() ); + FileSystemWrapper writer = fileSystem.openForWrite( path, true, Function.identity() ); return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) }; } default: @@ -365,10 +367,7 @@ public class FSAPI implements ILuaAPI } catch( FileSystemException e ) { - return new Object[] { - null, - e.getMessage() - }; + return new Object[] { null, e.getMessage() }; } } @@ -385,7 +384,7 @@ public class FSAPI implements ILuaAPI { try { - return this.fileSystem.exists( path ) ? new Object[] { this.fileSystem.getMountLabel( path ) } : null; + return fileSystem.exists( path ) ? new Object[] { fileSystem.getMountLabel( path ) } : null; } catch( FileSystemException e ) { @@ -394,7 +393,8 @@ public class FSAPI implements ILuaAPI } /** - * Returns the amount of free space available on the drive the path is located on. + * Returns the amount of free space available on the drive the path is + * located on. * * @param path The path to check the free space for. * @return The amount of free space available, in bytes. @@ -406,7 +406,7 @@ public class FSAPI implements ILuaAPI { try { - long freeSpace = this.fileSystem.getFreeSpace( path ); + long freeSpace = fileSystem.getFreeSpace( path ); return freeSpace >= 0 ? freeSpace : "unlimited"; } catch( FileSystemException e ) @@ -418,8 +418,10 @@ public class FSAPI implements ILuaAPI /** * Searches for files matching a string with wildcards. * - * This string is formatted like a normal path string, but can include any number of wildcards ({@code *}) to look for files matching anything. For - * example, {@code rom/* /command*} will look for any path starting with {@code command} inside any subdirectory of {@code /rom}. + * This string is formatted like a normal path string, but can include any + * number of wildcards ({@code *}) to look for files matching anything. + * For example, {@code rom/* /command*} will look for any path starting with + * {@code command} inside any subdirectory of {@code /rom}. * * @param path The wildcard-qualified path to search for. * @return A list of paths that match the search string. @@ -430,8 +432,8 @@ public class FSAPI implements ILuaAPI { try { - this.environment.addTrackingChange( TrackingField.FS_OPS ); - return this.fileSystem.find( path ); + environment.addTrackingChange( TrackingField.FS_OPS ); + return fileSystem.find( path ); } catch( FileSystemException e ) { @@ -442,20 +444,22 @@ public class FSAPI implements ILuaAPI /** * Returns true if a path is mounted to the parent filesystem. * - * The root filesystem "/" is considered a mount, along with disk folders and the rom folder. Other programs (such as network shares) can extend this to - * make other mount types by correctly assigning their return value for getDrive. + * The root filesystem "/" is considered a mount, along with disk folders and the rom folder. Other programs + * (such as network shares) can extend this to make other mount types by correctly assigning their return value for + * getDrive. * * @param path The path of the drive to get. * @return The drive's capacity. * @throws LuaException If the capacity cannot be determined. - * @cc.treturn number|nil This drive's capacity. This will be nil for "read-only" drives, such as the ROM or treasure disks. + * @cc.treturn number|nil This drive's capacity. This will be nil for "read-only" drives, such as the ROM or + * treasure disks. */ @LuaFunction public final Object getCapacity( String path ) throws LuaException { try { - OptionalLong capacity = this.fileSystem.getCapacity( path ); + OptionalLong capacity = fileSystem.getCapacity( path ); return capacity.isPresent() ? capacity.getAsLong() : null; } catch( FileSystemException e ) @@ -470,8 +474,8 @@ public class FSAPI implements ILuaAPI * The returned attributes table contains information about the size of the file, whether it is a directory, * when it was created and last modified, and whether it is read only. * - * The creation and modification times are given as the number of milliseconds since the UNIX epoch. This may be given to {@link OSAPI#date} in order to - * convert it to more usable form. + * The creation and modification times are given as the number of milliseconds since the UNIX epoch. This may be + * given to {@link OSAPI#date} in order to convert it to more usable form. * * @param path The path to get attributes for. * @return The resulting attributes. @@ -485,7 +489,7 @@ public class FSAPI implements ILuaAPI { try { - BasicFileAttributes attributes = this.fileSystem.getAttributes( path ); + BasicFileAttributes attributes = fileSystem.getAttributes( path ); Map result = new HashMap<>(); result.put( "modification", getFileTime( attributes.lastModifiedTime() ) ); result.put( "modified", getFileTime( attributes.lastModifiedTime() ) ); diff --git a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java index 396232e92..2ba8f744b 100644 --- a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java @@ -37,7 +37,7 @@ public class HTTPAPI implements ILuaAPI { private final IAPIEnvironment apiEnvironment; - private final ResourceGroup checkUrls = new ResourceGroup<>(); + private final ResourceGroup checkUrls = new ResourceGroup<>( ResourceGroup.DEFAULT ); private final ResourceGroup requests = new ResourceQueue<>( () -> ComputerCraft.httpMaxRequests ); private final ResourceGroup websockets = new ResourceGroup<>( () -> ComputerCraft.httpMaxWebsockets ); @@ -127,7 +127,10 @@ public class HTTPAPI implements ILuaAPI HttpRequest request = new HttpRequest( requests, apiEnvironment, address, postString, headers, binary, redirect ); // Make the request - request.queue( r -> r.request( uri, httpMethod ) ); + if( !request.queue( r -> r.request( uri, httpMethod ) ) ) + { + throw new LuaException( "Too many ongoing HTTP requests" ); + } return new Object[] { true }; } @@ -138,12 +141,15 @@ public class HTTPAPI implements ILuaAPI } @LuaFunction - public final Object[] checkURL( String address ) + public final Object[] checkURL( String address ) throws LuaException { try { URI uri = HttpRequest.checkUri( address ); - new CheckUrl( checkUrls, apiEnvironment, address, uri ).queue( CheckUrl::run ); + if( !new CheckUrl( checkUrls, apiEnvironment, address, uri ).queue( CheckUrl::run ) ) + { + throw new LuaException( "Too many ongoing checkUrl calls" ); + } return new Object[] { true }; } diff --git a/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java index 8376b598d..25960c580 100644 --- a/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java +++ b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.peripheral.IPeripheral; @@ -21,6 +20,12 @@ public interface IAPIEnvironment { String TIMER_EVENT = "timer"; + @FunctionalInterface + interface IPeripheralChangeListener + { + void onPeripheralChanged( ComputerSide side, @Nullable IPeripheral newPeripheral ); + } + int getComputerID(); @Nonnull @@ -65,16 +70,10 @@ public interface IAPIEnvironment void cancelTimer( int id ); - default void addTrackingChange( @Nonnull TrackingField field ) - { - this.addTrackingChange( field, 1 ); - } - void addTrackingChange( @Nonnull TrackingField field, long change ); - @FunctionalInterface - interface IPeripheralChangeListener + default void addTrackingChange( @Nonnull TrackingField field ) { - void onPeripheralChanged( ComputerSide side, @Nullable IPeripheral newPeripheral ); + addTrackingChange( field, 1 ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java b/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java index fbb486296..3293d2b7c 100644 --- a/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java +++ b/src/main/java/dan200/computercraft/core/apis/LuaDateTime.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.lua.LuaException; @@ -21,9 +20,6 @@ import java.util.function.LongUnaryOperator; final class LuaDateTime { - private static final TemporalField CENTURY = map( ChronoField.YEAR, ValueRange.of( 0, 6 ), x -> (x / 100) % 100 ); - private static final TemporalField ZERO_WEEK = map( WeekFields.SUNDAY_START.dayOfWeek(), ValueRange.of( 0, 6 ), x -> x - 1 ); - private LuaDateTime() { } @@ -42,10 +38,7 @@ final class LuaDateTime formatter.appendLiteral( c ); break; case '%': - if( i >= format.length() ) - { - break; - } + if( i >= format.length() ) break; switch( c = format.charAt( i++ ) ) { default: @@ -81,8 +74,7 @@ final class LuaDateTime format( formatter, "%m/%d/%y", offset ); break; case 'e': - formatter.padNext( 2 ) - .appendValue( ChronoField.DAY_OF_MONTH ); + formatter.padNext( 2 ).appendValue( ChronoField.DAY_OF_MONTH ); break; case 'F': format( formatter, "%Y-%m-%d", offset ); @@ -97,7 +89,7 @@ final class LuaDateTime formatter.appendValue( ChronoField.HOUR_OF_DAY, 2 ); break; case 'I': - formatter.appendValue( ChronoField.HOUR_OF_AMPM ); + formatter.appendValue( ChronoField.HOUR_OF_AMPM, 2 ); break; case 'j': formatter.appendValue( ChronoField.DAY_OF_YEAR, 3 ); @@ -176,49 +168,18 @@ final class LuaDateTime if( isDst != null ) { boolean requireDst = isDst; - for( ZoneOffset possibleOffset : ZoneOffset.systemDefault() - .getRules() - .getValidOffsets( time ) ) + for( ZoneOffset possibleOffset : ZoneOffset.systemDefault().getRules().getValidOffsets( time ) ) { Instant instant = time.toInstant( possibleOffset ); - if( possibleOffset.getRules() - .getDaylightSavings( instant ) - .isZero() == requireDst ) + if( possibleOffset.getRules().getDaylightSavings( instant ).isZero() == requireDst ) { return instant.getEpochSecond(); } } } - ZoneOffset offset = ZoneOffset.systemDefault() - .getRules() - .getOffset( time ); - return time.toInstant( offset ) - .getEpochSecond(); - } - - private static int getField( Map table, String field, int def ) throws LuaException - { - Object value = table.get( field ); - if( value instanceof Number ) - { - return ((Number) value).intValue(); - } - if( def < 0 ) - { - throw new LuaException( "field \"" + field + "\" missing in date table" ); - } - return def; - } - - private static Boolean getBoolField( Map table, String field ) throws LuaException - { - Object value = table.get( field ); - if( value instanceof Boolean || value == null ) - { - return (Boolean) value; - } - throw new LuaException( "field \"" + field + "\" missing in date table" ); + ZoneOffset offset = ZoneOffset.systemDefault().getRules().getOffset( time ); + return time.toInstant( offset ).getEpochSecond(); } static Map toTable( TemporalAccessor date, ZoneId offset, Instant instant ) @@ -232,12 +193,28 @@ final class LuaDateTime table.put( "sec", date.getLong( ChronoField.SECOND_OF_MINUTE ) ); table.put( "wday", date.getLong( WeekFields.SUNDAY_START.dayOfWeek() ) ); table.put( "yday", date.getLong( ChronoField.DAY_OF_YEAR ) ); - table.put( "isdst", - offset.getRules() - .isDaylightSavings( instant ) ); + table.put( "isdst", offset.getRules().isDaylightSavings( instant ) ); return table; } + private static int getField( Map table, String field, int def ) throws LuaException + { + Object value = table.get( field ); + if( value instanceof Number ) return ((Number) value).intValue(); + if( def < 0 ) throw new LuaException( "field \"" + field + "\" missing in date table" ); + return def; + } + + private static Boolean getBoolField( Map table, String field ) throws LuaException + { + Object value = table.get( field ); + if( value instanceof Boolean || value == null ) return (Boolean) value; + throw new LuaException( "field \"" + field + "\" missing in date table" ); + } + + private static final TemporalField CENTURY = map( ChronoField.YEAR, ValueRange.of( 0, 6 ), x -> (x / 100) % 100 ); + private static final TemporalField ZERO_WEEK = map( WeekFields.SUNDAY_START.dayOfWeek(), ValueRange.of( 0, 6 ), x -> x - 1 ); + private static TemporalField map( TemporalField field, ValueRange range, LongUnaryOperator convert ) { return new TemporalField() @@ -259,7 +236,7 @@ final class LuaDateTime @Override public ValueRange range() { - return this.range; + return range; } @Override @@ -283,7 +260,7 @@ final class LuaDateTime @Override public ValueRange rangeRefinedBy( TemporalAccessor temporal ) { - return this.range; + return range; } @Override diff --git a/src/main/java/dan200/computercraft/core/apis/OSAPI.java b/src/main/java/dan200/computercraft/core/apis/OSAPI.java index c34a8ef7d..9b59ffcef 100644 --- a/src/main/java/dan200/computercraft/core/apis/OSAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/OSAPI.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.lua.IArguments; @@ -33,16 +32,36 @@ public class OSAPI implements ILuaAPI { private final IAPIEnvironment apiEnvironment; - private final Int2ObjectMap m_alarms = new Int2ObjectOpenHashMap<>(); - private int m_clock; - private double m_time; - private int m_day; + private final Int2ObjectMap alarms = new Int2ObjectOpenHashMap<>(); + private int clock; + private double time; + private int day; - private int m_nextAlarmToken = 0; + private int nextAlarmToken = 0; + + private static class Alarm implements Comparable + { + final double time; + final int day; + + Alarm( double time, int day ) + { + this.time = time; + this.day = day; + } + + @Override + public int compareTo( @Nonnull Alarm o ) + { + double t = day * 24.0 + time; + double ot = day * 24.0 + time; + return Double.compare( t, ot ); + } + } public OSAPI( IAPIEnvironment environment ) { - this.apiEnvironment = environment; + apiEnvironment = environment; } @Override @@ -54,252 +73,57 @@ public class OSAPI implements ILuaAPI @Override public void startup() { - this.m_time = this.apiEnvironment.getComputerEnvironment() - .getTimeOfDay(); - this.m_day = this.apiEnvironment.getComputerEnvironment() - .getDay(); - this.m_clock = 0; + time = apiEnvironment.getComputerEnvironment().getTimeOfDay(); + day = apiEnvironment.getComputerEnvironment().getDay(); + clock = 0; - synchronized( this.m_alarms ) + synchronized( alarms ) { - this.m_alarms.clear(); + alarms.clear(); } } @Override public void update() { - this.m_clock++; + clock++; // Wait for all of our alarms - synchronized( this.m_alarms ) + synchronized( alarms ) { - double previousTime = this.m_time; - int previousDay = this.m_day; - double time = this.apiEnvironment.getComputerEnvironment() - .getTimeOfDay(); - int day = this.apiEnvironment.getComputerEnvironment() - .getDay(); + double previousTime = time; + int previousDay = day; + double time = apiEnvironment.getComputerEnvironment().getTimeOfDay(); + int day = apiEnvironment.getComputerEnvironment().getDay(); if( time > previousTime || day > previousDay ) { - double now = this.m_day * 24.0 + this.m_time; - Iterator> it = this.m_alarms.int2ObjectEntrySet() - .iterator(); + double now = this.day * 24.0 + this.time; + Iterator> it = alarms.int2ObjectEntrySet().iterator(); while( it.hasNext() ) { Int2ObjectMap.Entry entry = it.next(); Alarm alarm = entry.getValue(); - double t = alarm.m_day * 24.0 + alarm.m_time; + double t = alarm.day * 24.0 + alarm.time; if( now >= t ) { - this.apiEnvironment.queueEvent( "alarm", entry.getIntKey() ); + apiEnvironment.queueEvent( "alarm", entry.getIntKey() ); it.remove(); } } } - this.m_time = time; - this.m_day = day; + this.time = time; + this.day = day; } } @Override public void shutdown() { - synchronized( this.m_alarms ) + synchronized( alarms ) { - this.m_alarms.clear(); - } - } - - /** - * Adds an event to the event queue. This event can later be pulled with os.pullEvent. - * - * @param name The name of the event to queue. - * @param args The parameters of the event. - * @cc.tparam string name The name of the event to queue. - * @cc.param ... The parameters of the event. - * @cc.see os.pullEvent To pull the event queued - */ - @LuaFunction - public final void queueEvent( String name, IArguments args ) - { - this.apiEnvironment.queueEvent( name, - args.drop( 1 ) - .getAll() ); - } - - /** - * Starts a timer that will run for the specified number of seconds. Once the timer fires, a timer event will be added to the queue with the ID returned - * from this function as the first parameter. - * - * @param timer The number of seconds until the timer fires. - * @return The ID of the new timer. - * @throws LuaException If the time is below zero. - */ - @LuaFunction - public final int startTimer( double timer ) throws LuaException - { - return this.apiEnvironment.startTimer( Math.round( checkFinite( 0, timer ) / 0.05 ) ); - } - - /** - * Cancels a timer previously started with startTimer. This will stop the timer from firing. - * - * @param token The ID of the timer to cancel. - * @see #startTimer To start a timer. - */ - @LuaFunction - public final void cancelTimer( int token ) - { - this.apiEnvironment.cancelTimer( token ); - } - - /** - * Sets an alarm that will fire at the specified world time. When it fires, an alarm event will be added to the event queue. - * - * @param time The time at which to fire the alarm, in the range [0.0, 24.0). - * @return The ID of the alarm that was set. - * @throws LuaException If the time is out of range. - */ - @LuaFunction - public final int setAlarm( double time ) throws LuaException - { - checkFinite( 0, time ); - if( time < 0.0 || time >= 24.0 ) - { - throw new LuaException( "Number out of range" ); - } - synchronized( this.m_alarms ) - { - int day = time > this.m_time ? this.m_day : this.m_day + 1; - this.m_alarms.put( this.m_nextAlarmToken, new Alarm( time, day ) ); - return this.m_nextAlarmToken++; - } - } - - /** - * Cancels an alarm previously started with setAlarm. This will stop the alarm from firing. - * - * @param token The ID of the alarm to cancel. - * @see #setAlarm To set an alarm. - */ - @LuaFunction - public final void cancelAlarm( int token ) - { - synchronized( this.m_alarms ) - { - this.m_alarms.remove( token ); - } - } - - /** - * Shuts down the computer immediately. - */ - @LuaFunction( "shutdown" ) - public final void doShutdown() - { - this.apiEnvironment.shutdown(); - } - - /** - * Reboots the computer immediately. - */ - @LuaFunction( "reboot" ) - public final void doReboot() - { - this.apiEnvironment.reboot(); - } - - /** - * Returns the ID of the computer. - * - * @return The ID of the computer. - */ - @LuaFunction( { - "getComputerID", - "computerID" - } ) - public final int getComputerID() - { - return this.apiEnvironment.getComputerID(); - } - - /** - * Returns the label of the computer, or {@code nil} if none is set. - * - * @return The label of the computer. - * @cc.treturn string The label of the computer. - */ - @LuaFunction( { - "getComputerLabel", - "computerLabel" - } ) - public final Object[] getComputerLabel() - { - String label = this.apiEnvironment.getLabel(); - return label == null ? null : new Object[] { label }; - } - - /** - * Set the label of this computer. - * - * @param label The new label. May be {@code nil} in order to clear it. - */ - @LuaFunction - public final void setComputerLabel( Optional label ) - { - this.apiEnvironment.setLabel( StringUtil.normaliseLabel( label.orElse( null ) ) ); - } - - /** - * Returns the number of seconds that the computer has been running. - * - * @return The computer's uptime. - */ - @LuaFunction - public final double clock() - { - return this.m_clock * 0.05; - } - - /** - * Returns the current time depending on the string passed in. This will always be in the range [0.0, 24.0). - * - * * If called with {@code ingame}, the current world time will be returned. This is the default if nothing is passed. * If called with {@code utc}, - * returns the hour of the day in UTC time. * If called with {@code local}, returns the hour of the day in the timezone the server is located in. - * - * This function can also be called with a table returned from {@link #date}, which will convert the date fields into a UNIX timestamp (number of - * seconds since 1 January 1970). - * - * @param args The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified. - * @return The hour of the selected locale, or a UNIX timestamp from the table, depending on the argument passed in. - * @throws LuaException If an invalid locale is passed. - * @cc.tparam [opt] string|table locale The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} - * locale if not specified. - * @see #date To get a date table that can be converted with this function. - */ - @LuaFunction - public final Object time( IArguments args ) throws LuaException - { - Object value = args.get( 0 ); - if( value instanceof Map ) - { - return LuaDateTime.fromTable( (Map) value ); - } - - String param = args.optString( 0, "ingame" ); - switch( param.toLowerCase( Locale.ROOT ) ) - { - case "utc": // Get Hour of day (UTC) - return getTimeForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); - case "local": // Get Hour of day (local time) - return getTimeForCalendar( Calendar.getInstance() ); - case "ingame": // Get in-game hour - return this.m_time; - default: - throw new LuaException( "Unsupported operation" ); + alarms.clear(); } } @@ -311,34 +135,6 @@ public class OSAPI implements ILuaAPI return time; } - /** - * Returns the day depending on the locale specified. - * - * * If called with {@code ingame}, returns the number of days since the world was created. This is the default. * If called with {@code utc}, returns - * the number of days since 1 January 1970 in the UTC timezone. * If called with {@code local}, returns the number of days since 1 January 1970 in the - * server's local timezone. - * - * @param args The locale to get the day for. Defaults to {@code ingame} if not set. - * @return The day depending on the selected locale. - * @throws LuaException If an invalid locale is passed. - */ - @LuaFunction - public final int day( Optional args ) throws LuaException - { - switch( args.orElse( "ingame" ) - .toLowerCase( Locale.ROOT ) ) - { - case "utc": // Get numbers of days since 1970-01-01 (utc) - return getDayForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); - case "local": // Get numbers of days since 1970-01-01 (local time) - return getDayForCalendar( Calendar.getInstance() ); - case "ingame":// Get game day - return this.m_day; - default: - throw new LuaException( "Unsupported operation" ); - } - } - private static int getDayForCalendar( Calendar c ) { GregorianCalendar g = c instanceof GregorianCalendar ? (GregorianCalendar) c : new GregorianCalendar(); @@ -352,12 +148,244 @@ public class OSAPI implements ILuaAPI return day; } + private static long getEpochForCalendar( Calendar c ) + { + return c.getTime().getTime(); + } + + /** + * Adds an event to the event queue. This event can later be pulled with + * os.pullEvent. + * + * @param name The name of the event to queue. + * @param args The parameters of the event. + * @cc.tparam string name The name of the event to queue. + * @cc.param ... The parameters of the event. + * @cc.see os.pullEvent To pull the event queued + */ + @LuaFunction + public final void queueEvent( String name, IArguments args ) + { + apiEnvironment.queueEvent( name, args.drop( 1 ).getAll() ); + } + + /** + * Starts a timer that will run for the specified number of seconds. Once + * the timer fires, a {@code timer} event will be added to the queue with + * the ID returned from this function as the first parameter. + * + * As with @{os.sleep|sleep}, {@code timer} will automatically be rounded up + * to the nearest multiple of 0.05 seconds, as it waits for a fixed amount + * of world ticks. + * + * @param timer The number of seconds until the timer fires. + * @return The ID of the new timer. This can be used to filter the + * {@code timer} event, or {@link #cancelTimer cancel the timer}. + * @throws LuaException If the time is below zero. + * @see #cancelTimer To cancel a timer. + */ + @LuaFunction + public final int startTimer( double timer ) throws LuaException + { + return apiEnvironment.startTimer( Math.round( checkFinite( 0, timer ) / 0.05 ) ); + } + + /** + * Cancels a timer previously started with startTimer. This will stop the + * timer from firing. + * + * @param token The ID of the timer to cancel. + * @see #startTimer To start a timer. + */ + @LuaFunction + public final void cancelTimer( int token ) + { + apiEnvironment.cancelTimer( token ); + } + + /** + * Sets an alarm that will fire at the specified world time. When it fires, + * an {@code alarm} event will be added to the event queue with the ID + * returned from this function as the first parameter. + * + * @param time The time at which to fire the alarm, in the range [0.0, 24.0). + * @return The ID of the new alarm. This can be used to filter the + * {@code alarm} event, or {@link #cancelAlarm cancel the alarm}. + * @throws LuaException If the time is out of range. + * @see #cancelAlarm To cancel an alarm. + */ + @LuaFunction + public final int setAlarm( double time ) throws LuaException + { + checkFinite( 0, time ); + if( time < 0.0 || time >= 24.0 ) throw new LuaException( "Number out of range" ); + synchronized( alarms ) + { + int day = time > this.time ? this.day : this.day + 1; + alarms.put( nextAlarmToken, new Alarm( time, day ) ); + return nextAlarmToken++; + } + } + + /** + * Cancels an alarm previously started with setAlarm. This will stop the + * alarm from firing. + * + * @param token The ID of the alarm to cancel. + * @see #setAlarm To set an alarm. + */ + @LuaFunction + public final void cancelAlarm( int token ) + { + synchronized( alarms ) + { + alarms.remove( token ); + } + } + + /** + * Shuts down the computer immediately. + */ + @LuaFunction( "shutdown" ) + public final void doShutdown() + { + apiEnvironment.shutdown(); + } + + /** + * Reboots the computer immediately. + */ + @LuaFunction( "reboot" ) + public final void doReboot() + { + apiEnvironment.reboot(); + } + + /** + * Returns the ID of the computer. + * + * @return The ID of the computer. + */ + @LuaFunction( { "getComputerID", "computerID" } ) + public final int getComputerID() + { + return apiEnvironment.getComputerID(); + } + + /** + * Returns the label of the computer, or {@code nil} if none is set. + * + * @return The label of the computer. + * @cc.treturn string The label of the computer. + */ + @LuaFunction( { "getComputerLabel", "computerLabel" } ) + public final Object[] getComputerLabel() + { + String label = apiEnvironment.getLabel(); + return label == null ? null : new Object[] { label }; + } + + /** + * Set the label of this computer. + * + * @param label The new label. May be {@code nil} in order to clear it. + */ + @LuaFunction + public final void setComputerLabel( Optional label ) + { + apiEnvironment.setLabel( StringUtil.normaliseLabel( label.orElse( null ) ) ); + } + + /** + * Returns the number of seconds that the computer has been running. + * + * @return The computer's uptime. + */ + @LuaFunction + public final double clock() + { + return clock * 0.05; + } + + /** + * Returns the current time depending on the string passed in. This will + * always be in the range [0.0, 24.0). + * + * * If called with {@code ingame}, the current world time will be returned. + * This is the default if nothing is passed. + * * If called with {@code utc}, returns the hour of the day in UTC time. + * * If called with {@code local}, returns the hour of the day in the + * timezone the server is located in. + * + * This function can also be called with a table returned from {@link #date}, + * which will convert the date fields into a UNIX timestamp (number of + * seconds since 1 January 1970). + * + * @param args The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified. + * @return The hour of the selected locale, or a UNIX timestamp from the table, depending on the argument passed in. + * @throws LuaException If an invalid locale is passed. + * @cc.tparam [opt] string|table locale The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified. + * @see #date To get a date table that can be converted with this function. + */ + @LuaFunction + public final Object time( IArguments args ) throws LuaException + { + Object value = args.get( 0 ); + if( value instanceof Map ) return LuaDateTime.fromTable( (Map) value ); + + String param = args.optString( 0, "ingame" ); + switch( param.toLowerCase( Locale.ROOT ) ) + { + case "utc": // Get Hour of day (UTC) + return getTimeForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); + case "local": // Get Hour of day (local time) + return getTimeForCalendar( Calendar.getInstance() ); + case "ingame": // Get in-game hour + return time; + default: + throw new LuaException( "Unsupported operation" ); + } + } + + /** + * Returns the day depending on the locale specified. + * + * * If called with {@code ingame}, returns the number of days since the + * world was created. This is the default. + * * If called with {@code utc}, returns the number of days since 1 January + * 1970 in the UTC timezone. + * * If called with {@code local}, returns the number of days since 1 + * January 1970 in the server's local timezone. + * + * @param args The locale to get the day for. Defaults to {@code ingame} if not set. + * @return The day depending on the selected locale. + * @throws LuaException If an invalid locale is passed. + */ + @LuaFunction + public final int day( Optional args ) throws LuaException + { + switch( args.orElse( "ingame" ).toLowerCase( Locale.ROOT ) ) + { + case "utc": // Get numbers of days since 1970-01-01 (utc) + return getDayForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); + case "local": // Get numbers of days since 1970-01-01 (local time) + return getDayForCalendar( Calendar.getInstance() ); + case "ingame":// Get game day + return day; + default: + throw new LuaException( "Unsupported operation" ); + } + } + /** * Returns the number of milliseconds since an epoch depending on the locale. * - * * If called with {@code ingame}, returns the number of milliseconds since the world was created. This is the default. * If called with {@code utc}, - * returns the number of milliseconds since 1 January 1970 in the UTC timezone. * If called with {@code local}, returns the number of seconds since 1 January - * 1970 in the server's local timezone. + * * If called with {@code ingame}, returns the number of milliseconds since the + * world was created. This is the default. + * * If called with {@code utc}, returns the number of milliseconds since 1 + * January 1970 in the UTC timezone. + * * If called with {@code local}, returns the number of milliseconds since 1 + * January 1970 in the server's local timezone. * * @param args The locale to get the milliseconds for. Defaults to {@code ingame} if not set. * @return The milliseconds since the epoch depending on the selected locale. @@ -366,8 +394,7 @@ public class OSAPI implements ILuaAPI @LuaFunction public final long epoch( Optional args ) throws LuaException { - switch( args.orElse( "ingame" ) - .toLowerCase( Locale.ROOT ) ) + switch( args.orElse( "ingame" ).toLowerCase( Locale.ROOT ) ) { case "utc": { @@ -383,30 +410,29 @@ public class OSAPI implements ILuaAPI } case "ingame": // Get in-game epoch - synchronized( this.m_alarms ) + synchronized( alarms ) { - return this.m_day * 86400000L + (long) (this.m_time * 3600000.0); + return day * 86400000L + (long) (time * 3600000.0); } default: throw new LuaException( "Unsupported operation" ); } } - private static long getEpochForCalendar( Calendar c ) - { - return c.getTime() - .getTime(); - } - /** - * Returns a date string (or table) using a specified format string and optional time to format. + * Returns a date string (or table) using a specified format string and + * optional time to format. * - * The format string takes the same formats as C's {@code strftime} function (http://www.cplusplus.com/reference/ctime/strftime/). In extension, it can - * be prefixed with an exclamation mark ({@code !}) to use UTC time instead of the server's local timezone. + * The format string takes the same formats as C's {@code strftime} function + * (http://www.cplusplus.com/reference/ctime/strftime/). In extension, it + * can be prefixed with an exclamation mark ({@code !}) to use UTC time + * instead of the server's local timezone. * - * If the format is exactly {@code *t} (optionally prefixed with {@code !}), a table will be returned instead. This table has fields for the year, - * month, day, hour, minute, second, day of the week, day of the year, and whether Daylight Savings Time is in effect. This table can be converted to a - * UNIX timestamp (days since 1 January 1970) with {@link #date}. + * If the format is exactly {@code *t} (optionally prefixed with {@code !}), a + * table will be returned instead. This table has fields for the year, month, + * day, hour, minute, second, day of the week, day of the year, and whether + * Daylight Savings Time is in effect. This table can be converted to a UNIX + * timestamp (days since 1 January 1970) with {@link #date}. * * @param formatA The format of the string to return. This defaults to {@code %c}, which expands to a string similar to "Sat Dec 24 16:58:00 2011". * @param timeA The time to convert to a string. This defaults to the current time. @@ -417,8 +443,7 @@ public class OSAPI implements ILuaAPI public final Object date( Optional formatA, Optional timeA ) throws LuaException { String format = formatA.orElse( "%c" ); - long time = timeA.orElseGet( () -> Instant.now() - .getEpochSecond() ); + long time = timeA.orElseGet( () -> Instant.now().getEpochSecond() ); Instant instant = Instant.ofEpochSecond( time ); ZonedDateTime date; @@ -432,40 +457,15 @@ public class OSAPI implements ILuaAPI else { ZoneId id = ZoneId.systemDefault(); - offset = id.getRules() - .getOffset( instant ); + offset = id.getRules().getOffset( instant ); date = ZonedDateTime.ofInstant( instant, id ); } - if( format.equals( "*t" ) ) - { - return LuaDateTime.toTable( date, offset, instant ); - } + if( format.equals( "*t" ) ) return LuaDateTime.toTable( date, offset, instant ); DateTimeFormatterBuilder formatter = new DateTimeFormatterBuilder(); LuaDateTime.format( formatter, format, offset ); - return formatter.toFormatter( Locale.ROOT ) - .format( date ); - } - - private static class Alarm implements Comparable - { - final double m_time; - final int m_day; - - Alarm( double time, int day ) - { - this.m_time = time; - this.m_day = day; - } - - @Override - public int compareTo( @Nonnull Alarm o ) - { - double t = this.m_day * 24.0 + this.m_time; - double ot = this.m_day * 24.0 + this.m_time; - return Double.compare( t, ot ); - } + return formatter.toFormatter( Locale.ROOT ).format( date ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java index 58c40004e..02e382090 100644 --- a/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.filesystem.IMount; @@ -31,213 +30,6 @@ import java.util.*; */ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener { - private final IAPIEnvironment environment; - private final PeripheralWrapper[] peripherals = new PeripheralWrapper[6]; - private boolean running; - - public PeripheralAPI( IAPIEnvironment environment ) - { - this.environment = environment; - this.environment.setPeripheralChangeListener( this ); - this.running = false; - } - - public static Map getMethods( IPeripheral peripheral ) - { - String[] dynamicMethods = peripheral instanceof IDynamicPeripheral ? Objects.requireNonNull( ((IDynamicPeripheral) peripheral).getMethodNames(), - "Peripheral methods cannot be null" ) : - LuaMethod.EMPTY_METHODS; - - List> methods = PeripheralMethod.GENERATOR.getMethods( peripheral.getClass() ); - - Map methodMap = new HashMap<>( methods.size() + dynamicMethods.length ); - for( int i = 0; i < dynamicMethods.length; i++ ) - { - methodMap.put( dynamicMethods[i], PeripheralMethod.DYNAMIC.get( i ) ); - } - for( NamedMethod method : methods ) - { - methodMap.put( method.getName(), method.getMethod() ); - } - return methodMap; - } - - // IPeripheralChangeListener - - @Override - public void onPeripheralChanged( ComputerSide side, IPeripheral newPeripheral ) - { - synchronized( this.peripherals ) - { - int index = side.ordinal(); - if( this.peripherals[index] != null ) - { - // Queue a detachment - final PeripheralWrapper wrapper = this.peripherals[index]; - if( wrapper.isAttached() ) - { - wrapper.detach(); - } - - // Queue a detachment event - this.environment.queueEvent( "peripheral_detach", side.getName() ); - } - - // Assign the new peripheral - this.peripherals[index] = newPeripheral == null ? null : new PeripheralWrapper( newPeripheral, side.getName() ); - - if( this.peripherals[index] != null ) - { - // Queue an attachment - final PeripheralWrapper wrapper = this.peripherals[index]; - if( this.running && !wrapper.isAttached() ) - { - wrapper.attach(); - } - - // Queue an attachment event - this.environment.queueEvent( "peripheral", side.getName() ); - } - } - } - - @Override - public String[] getNames() - { - return new String[] { "peripheral" }; - } - - @Override - public void startup() - { - synchronized( this.peripherals ) - { - this.running = true; - for( int i = 0; i < 6; i++ ) - { - PeripheralWrapper wrapper = this.peripherals[i]; - if( wrapper != null && !wrapper.isAttached() ) - { - wrapper.attach(); - } - } - } - } - - @Override - public void shutdown() - { - synchronized( this.peripherals ) - { - this.running = false; - for( int i = 0; i < 6; i++ ) - { - PeripheralWrapper wrapper = this.peripherals[i]; - if( wrapper != null && wrapper.isAttached() ) - { - wrapper.detach(); - } - } - } - } - - @LuaFunction - public final boolean isPresent( String sideName ) - { - ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); - if( side != null ) - { - synchronized( this.peripherals ) - { - PeripheralWrapper p = this.peripherals[side.ordinal()]; - if( p != null ) - { - return true; - } - } - } - return false; - } - - @LuaFunction - public final Object[] getType( String sideName ) - { - ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); - if( side == null ) - { - return null; - } - - synchronized( this.peripherals ) - { - PeripheralWrapper p = this.peripherals[side.ordinal()]; - if( p != null ) - { - return new Object[] { p.getType() }; - } - } - return null; - } - - @LuaFunction - public final Object[] getMethods( String sideName ) - { - ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); - if( side == null ) - { - return null; - } - - synchronized( this.peripherals ) - { - PeripheralWrapper p = this.peripherals[side.ordinal()]; - if( p != null ) - { - return new Object[] { p.getMethods() }; - } - } - return null; - } - - @LuaFunction - public final MethodResult call( ILuaContext context, IArguments args ) throws LuaException - { - ComputerSide side = ComputerSide.valueOfInsensitive( args.getString( 0 ) ); - String methodName = args.getString( 1 ); - IArguments methodArgs = args.drop( 2 ); - - if( side == null ) - { - throw new LuaException( "No peripheral attached" ); - } - - PeripheralWrapper p; - synchronized( this.peripherals ) - { - p = this.peripherals[side.ordinal()]; - } - if( p == null ) - { - throw new LuaException( "No peripheral attached" ); - } - - try - { - return p.call( context, methodName, methodArgs ) - .adjustError( 1 ); - } - catch( LuaException e ) - { - // We increase the error level by one in order to shift the error level to where peripheral.call was - // invoked. It would be possible to do it in Lua code, but would add significantly more overhead. - if( e.getLevel() > 0 ) - { - throw new FastLuaException( e.getMessage(), e.getLevel() + 1 ); - } - throw e; - } - } - private class PeripheralWrapper extends ComputerAccess { private final String side; @@ -249,54 +41,54 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange PeripheralWrapper( IPeripheral peripheral, String side ) { - super( PeripheralAPI.this.environment ); + super( environment ); this.side = side; this.peripheral = peripheral; - this.attached = false; + attached = false; - this.type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); + type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); - this.methodMap = PeripheralAPI.getMethods( peripheral ); - } - - public String getType() - { - return this.type; + methodMap = PeripheralAPI.getMethods( peripheral ); } public IPeripheral getPeripheral() { - return this.peripheral; + return peripheral; + } + + public String getType() + { + return type; } public Collection getMethods() { - return this.methodMap.keySet(); + return methodMap.keySet(); + } + + public synchronized boolean isAttached() + { + return attached; } public synchronized void attach() { - this.attached = true; - this.peripheral.attach( this ); + attached = true; + peripheral.attach( this ); } public void detach() { // Call detach - this.peripheral.detach( this ); + peripheral.detach( this ); synchronized( this ) { // Unmount everything the detach function forgot to do - this.unmountAll(); + unmountAll(); } - this.attached = false; - } - - public synchronized boolean isAttached() - { - return this.attached; + attached = false; } public MethodResult call( ILuaContext context, String methodName, IArguments arguments ) throws LuaException @@ -304,100 +96,64 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange PeripheralMethod method; synchronized( this ) { - method = this.methodMap.get( methodName ); + method = methodMap.get( methodName ); } - if( method == null ) - { - throw new LuaException( "No such method " + methodName ); - } + if( method == null ) throw new LuaException( "No such method " + methodName ); - PeripheralAPI.this.environment.addTrackingChange( TrackingField.PERIPHERAL_OPS ); - return method.apply( this.peripheral, context, this, arguments ); + environment.addTrackingChange( TrackingField.PERIPHERAL_OPS ); + return method.apply( peripheral, context, this, arguments ); } // IComputerAccess implementation @Override public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName ) { - if( !this.attached ) - { - throw new NotAttachedException(); - } + if( !attached ) throw new NotAttachedException(); return super.mount( desiredLoc, mount, driveName ); } @Override public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName ) { - if( !this.attached ) - { - throw new NotAttachedException(); - } + if( !attached ) throw new NotAttachedException(); return super.mountWritable( desiredLoc, mount, driveName ); } @Override public synchronized void unmount( String location ) { - if( !this.attached ) - { - throw new NotAttachedException(); - } + if( !attached ) throw new NotAttachedException(); super.unmount( location ); } @Override public int getID() { - if( !this.attached ) - { - throw new NotAttachedException(); - } + if( !attached ) throw new NotAttachedException(); return super.getID(); } @Override public void queueEvent( @Nonnull String event, Object... arguments ) { - if( !this.attached ) - { - throw new NotAttachedException(); - } + if( !attached ) throw new NotAttachedException(); super.queueEvent( event, arguments ); } - @Nonnull - @Override - public IWorkMonitor getMainThreadMonitor() - { - if( !this.attached ) - { - throw new NotAttachedException(); - } - return super.getMainThreadMonitor(); - } - - @Nonnull @Override public String getAttachmentName() { - if( !this.attached ) - { - throw new NotAttachedException(); - } - return this.side; + if( !attached ) throw new NotAttachedException(); + return side; } @Nonnull @Override public Map getAvailablePeripherals() { - if( !this.attached ) - { - throw new NotAttachedException(); - } + if( !attached ) throw new NotAttachedException(); Map peripherals = new HashMap<>(); for( PeripheralWrapper wrapper : PeripheralAPI.this.peripherals ) @@ -415,15 +171,11 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange @Override public IPeripheral getAvailablePeripheral( @Nonnull String name ) { - if( !this.attached ) - { - throw new NotAttachedException(); - } + if( !attached ) throw new NotAttachedException(); - for( PeripheralWrapper wrapper : PeripheralAPI.this.peripherals ) + for( PeripheralWrapper wrapper : peripherals ) { - if( wrapper != null && wrapper.isAttached() && wrapper.getAttachmentName() - .equals( name ) ) + if( wrapper != null && wrapper.isAttached() && wrapper.getAttachmentName().equals( name ) ) { return wrapper.getPeripheral(); } @@ -431,6 +183,186 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange return null; } + @Nonnull + @Override + public IWorkMonitor getMainThreadMonitor() + { + if( !attached ) throw new NotAttachedException(); + return super.getMainThreadMonitor(); + } + } + private final IAPIEnvironment environment; + private final PeripheralWrapper[] peripherals = new PeripheralWrapper[6]; + private boolean running; + + public PeripheralAPI( IAPIEnvironment environment ) + { + this.environment = environment; + this.environment.setPeripheralChangeListener( this ); + running = false; + } + + // IPeripheralChangeListener + + @Override + public void onPeripheralChanged( ComputerSide side, IPeripheral newPeripheral ) + { + synchronized( peripherals ) + { + int index = side.ordinal(); + if( peripherals[index] != null ) + { + // Queue a detachment + final PeripheralWrapper wrapper = peripherals[index]; + if( wrapper.isAttached() ) wrapper.detach(); + + // Queue a detachment event + environment.queueEvent( "peripheral_detach", side.getName() ); + } + + // Assign the new peripheral + peripherals[index] = newPeripheral == null ? null + : new PeripheralWrapper( newPeripheral, side.getName() ); + + if( peripherals[index] != null ) + { + // Queue an attachment + final PeripheralWrapper wrapper = peripherals[index]; + if( running && !wrapper.isAttached() ) wrapper.attach(); + + // Queue an attachment event + environment.queueEvent( "peripheral", side.getName() ); + } + } + } + + @Override + public String[] getNames() + { + return new String[] { "peripheral" }; + } + + @Override + public void startup() + { + synchronized( peripherals ) + { + running = true; + for( int i = 0; i < 6; i++ ) + { + PeripheralWrapper wrapper = peripherals[i]; + if( wrapper != null && !wrapper.isAttached() ) wrapper.attach(); + } + } + } + + @Override + public void shutdown() + { + synchronized( peripherals ) + { + running = false; + for( int i = 0; i < 6; i++ ) + { + PeripheralWrapper wrapper = peripherals[i]; + if( wrapper != null && wrapper.isAttached() ) + { + wrapper.detach(); + } + } + } + } + + @LuaFunction + public final boolean isPresent( String sideName ) + { + ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); + if( side != null ) + { + synchronized( peripherals ) + { + PeripheralWrapper p = peripherals[side.ordinal()]; + if( p != null ) return true; + } + } + return false; + } + + @LuaFunction + public final Object[] getType( String sideName ) + { + ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); + if( side == null ) return null; + + synchronized( peripherals ) + { + PeripheralWrapper p = peripherals[side.ordinal()]; + if( p != null ) return new Object[] { p.getType() }; + } + return null; + } + + @LuaFunction + public final Object[] getMethods( String sideName ) + { + ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); + if( side == null ) return null; + + synchronized( peripherals ) + { + PeripheralWrapper p = peripherals[side.ordinal()]; + if( p != null ) return new Object[] { p.getMethods() }; + } + return null; + } + + @LuaFunction + public final MethodResult call( ILuaContext context, IArguments args ) throws LuaException + { + ComputerSide side = ComputerSide.valueOfInsensitive( args.getString( 0 ) ); + String methodName = args.getString( 1 ); + IArguments methodArgs = args.drop( 2 ); + + if( side == null ) throw new LuaException( "No peripheral attached" ); + + PeripheralWrapper p; + synchronized( peripherals ) + { + p = peripherals[side.ordinal()]; + } + if( p == null ) throw new LuaException( "No peripheral attached" ); + + try + { + return p.call( context, methodName, methodArgs ).adjustError( 1 ); + } + catch( LuaException e ) + { + // We increase the error level by one in order to shift the error level to where peripheral.call was + // invoked. It would be possible to do it in Lua code, but would add significantly more overhead. + if( e.getLevel() > 0 ) throw new FastLuaException( e.getMessage(), e.getLevel() + 1 ); + throw e; + } + } + + public static Map getMethods( IPeripheral peripheral ) + { + String[] dynamicMethods = peripheral instanceof IDynamicPeripheral + ? Objects.requireNonNull( ((IDynamicPeripheral) peripheral).getMethodNames(), "Peripheral methods cannot be null" ) + : LuaMethod.EMPTY_METHODS; + + List> methods = PeripheralMethod.GENERATOR.getMethods( peripheral.getClass() ); + + Map methodMap = new HashMap<>( methods.size() + dynamicMethods.length ); + for( int i = 0; i < dynamicMethods.length; i++ ) + { + methodMap.put( dynamicMethods[i], PeripheralMethod.DYNAMIC.get( i ) ); + } + for( NamedMethod method : methods ) + { + methodMap.put( method.getName(), method.getMethod() ); + } + return methodMap; } } diff --git a/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java b/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java index 90cedcfe7..186199302 100644 --- a/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.lua.ILuaAPI; @@ -14,37 +13,43 @@ import dan200.computercraft.core.computer.ComputerSide; /** * Interact with redstone attached to this computer. * - * The {@link RedstoneAPI} library exposes three "types" of redstone control: - Binary input/output ({@link #setOutput}/{@link #getInput}): These simply - * check if a redstone wire has any input or output. A signal strength of 1 and 15 are treated the same. - Analogue input/output ({@link - * #setAnalogOutput}/{@link #getAnalogInput}): These work with the actual signal strength of the redstone wired, from 0 to 15. - Bundled cables ({@link - * #setBundledOutput}/{@link #getBundledInput}): These interact with "bundled" cables, such as those from Project:Red. These allow you to send 16 separate - * on/off signals. Each channel corresponds to a colour, with the first being @{colors.white} and the last @{colors.black}. + * The {@link RedstoneAPI} library exposes three "types" of redstone control: + * - Binary input/output ({@link #setOutput}/{@link #getInput}): These simply check if a redstone wire has any input or + * output. A signal strength of 1 and 15 are treated the same. + * - Analogue input/output ({@link #setAnalogOutput}/{@link #getAnalogInput}): These work with the actual signal + * strength of the redstone wired, from 0 to 15. + * - Bundled cables ({@link #setBundledOutput}/{@link #getBundledInput}): These interact with "bundled" cables, such + * as those from Project:Red. These allow you to send 16 separate on/off signals. Each channel corresponds to a + * colour, with the first being @{colors.white} and the last @{colors.black}. * - * Whenever a redstone input changes, a {@code redstone} event will be fired. This may be used instead of repeativly polling. + * Whenever a redstone input changes, a {@code redstone} event will be fired. This may be used instead of repeativly + * polling. * - * This module may also be referred to as {@code rs}. For example, one may call {@code rs.getSides()} instead of {@link #getSides}. + * This module may also be referred to as {@code rs}. For example, one may call {@code rs.getSides()} instead of + * {@link #getSides}. * * @cc.usage Toggle the redstone signal above the computer every 0.5 seconds. * *
    - *     while true do
    - *       redstone.setOutput("top", not redstone.getOutput("top"))
    - *       sleep(0.5)
    - *     end
    - *     
    + * while true do + * redstone.setOutput("top", not redstone.getOutput("top")) + * sleep(0.5) + * end + *
    * @cc.usage Mimic a redstone comparator in [subtraction mode][comparator]. * *
    - *     while true do
    - *       local rear = rs.getAnalogueInput("back")
    - *       local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
    - *       rs.setAnalogueOutput("front", math.max(rear - sides, 0))
    + * while true do
    + *   local rear = rs.getAnalogueInput("back")
    + *   local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
    + *   rs.setAnalogueOutput("front", math.max(rear - sides, 0))
      *
    - *       os.pullEvent("redstone") -- Wait for a change to inputs.
    - *     end
    - *     
    + * os.pullEvent("redstone") -- Wait for a change to inputs. + * end + *
    * - * [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on the Minecraft wiki." + * [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on + * the Minecraft wiki." * @cc.module redstone */ public class RedstoneAPI implements ILuaAPI @@ -59,14 +64,12 @@ public class RedstoneAPI implements ILuaAPI @Override public String[] getNames() { - return new String[] { - "rs", - "redstone" - }; + return new String[] { "rs", "redstone" }; } /** - * Returns a table containing the six sides of the computer. Namely, "top", "bottom", "left", "right", "front" and "back". + * Returns a table containing the six sides of the computer. Namely, "top", "bottom", "left", "right", "front" and + * "back". * * @return A table of valid sides. */ @@ -85,7 +88,7 @@ public class RedstoneAPI implements ILuaAPI @LuaFunction public final void setOutput( ComputerSide side, boolean on ) { - this.environment.setOutput( side, on ? 15 : 0 ); + environment.setOutput( side, on ? 15 : 0 ); } /** @@ -98,7 +101,7 @@ public class RedstoneAPI implements ILuaAPI @LuaFunction public final boolean getOutput( ComputerSide side ) { - return this.environment.getOutput( side ) > 0; + return environment.getOutput( side ) > 0; } /** @@ -110,7 +113,7 @@ public class RedstoneAPI implements ILuaAPI @LuaFunction public final boolean getInput( ComputerSide side ) { - return this.environment.getInput( side ) > 0; + return environment.getInput( side ) > 0; } /** @@ -120,17 +123,11 @@ public class RedstoneAPI implements ILuaAPI * @param value The signal strength between 0 and 15. * @throws LuaException If {@code value} is not betwene 0 and 15. */ - @LuaFunction( { - "setAnalogOutput", - "setAnalogueOutput" - } ) + @LuaFunction( { "setAnalogOutput", "setAnalogueOutput" } ) public final void setAnalogOutput( ComputerSide side, int value ) throws LuaException { - if( value < 0 || value > 15 ) - { - throw new LuaException( "Expected number in range 0-15" ); - } - this.environment.setOutput( side, value ); + if( value < 0 || value > 15 ) throw new LuaException( "Expected number in range 0-15" ); + environment.setOutput( side, value ); } /** @@ -140,13 +137,10 @@ public class RedstoneAPI implements ILuaAPI * @return The output signal strength, between 0 and 15. * @see #setAnalogOutput */ - @LuaFunction( { - "getAnalogOutput", - "getAnalogueOutput" - } ) + @LuaFunction( { "getAnalogOutput", "getAnalogueOutput" } ) public final int getAnalogOutput( ComputerSide side ) { - return this.environment.getOutput( side ); + return environment.getOutput( side ); } /** @@ -155,13 +149,10 @@ public class RedstoneAPI implements ILuaAPI * @param side The side to get. * @return The input signal strength, between 0 and 15. */ - @LuaFunction( { - "getAnalogInput", - "getAnalogueInput" - } ) + @LuaFunction( { "getAnalogInput", "getAnalogueInput" } ) public final int getAnalogInput( ComputerSide side ) { - return this.environment.getInput( side ); + return environment.getInput( side ); } /** @@ -175,7 +166,7 @@ public class RedstoneAPI implements ILuaAPI @LuaFunction public final void setBundledOutput( ComputerSide side, int output ) { - this.environment.setBundledOutput( side, output ); + environment.setBundledOutput( side, output ); } /** @@ -187,7 +178,7 @@ public class RedstoneAPI implements ILuaAPI @LuaFunction public final int getBundledOutput( ComputerSide side ) { - return this.environment.getBundledOutput( side ); + return environment.getBundledOutput( side ); } /** @@ -211,14 +202,14 @@ public class RedstoneAPI implements ILuaAPI * @return If the colours are on. * @cc.usage Check if @{colors.white} and @{colors.black} are on above the computer. *
    -     *     print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
    -     *     
    + * print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black))) + *
    * @see #getBundledInput */ @LuaFunction public final boolean testBundledInput( ComputerSide side, int mask ) { - int input = this.environment.getBundledInput( side ); + int input = environment.getBundledInput( side ); return (input & mask) == mask; } } diff --git a/src/main/java/dan200/computercraft/core/apis/TableHelper.java b/src/main/java/dan200/computercraft/core/apis/TableHelper.java index cb584cd23..d16083534 100644 --- a/src/main/java/dan200/computercraft/core/apis/TableHelper.java +++ b/src/main/java/dan200/computercraft/core/apis/TableHelper.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.lua.LuaException; @@ -22,7 +21,32 @@ public final class TableHelper { private TableHelper() { - throw new IllegalStateException( "Cannot instantiate singleton " + this.getClass().getName() ); + throw new IllegalStateException( "Cannot instantiate singleton " + getClass().getName() ); + } + + @Nonnull + public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nullable Object actual ) + { + return badKey( key, expected, LuaValues.getType( actual ) ); + } + + @Nonnull + public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nonnull String actual ) + { + return new LuaException( "bad field '" + key + "' (" + expected + " expected, got " + actual + ")" ); + } + + public static double getNumberField( @Nonnull Map table, @Nonnull String key ) throws LuaException + { + Object value = table.get( key ); + if( value instanceof Number ) + { + return ((Number) value).doubleValue(); + } + else + { + throw badKey( key, "number", value ); + } } public static int getIntField( @Nonnull Map table, @Nonnull String key ) throws LuaException @@ -38,45 +62,11 @@ public final class TableHelper } } - @Nonnull - public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nullable Object actual ) - { - return badKey( key, expected, LuaValues.getType( actual ) ); - } - - @Nonnull - public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nonnull String actual ) - { - return new LuaException( "bad field '" + key + "' (" + expected + " expected, got " + actual + ")" ); - } - public static double getRealField( @Nonnull Map table, @Nonnull String key ) throws LuaException { return checkReal( key, getNumberField( table, key ) ); } - private static double checkReal( @Nonnull String key, double value ) throws LuaException - { - if( !Double.isFinite( value ) ) - { - throw badKey( key, "number", getNumericType( value ) ); - } - return value; - } - - public static double getNumberField( @Nonnull Map table, @Nonnull String key ) throws LuaException - { - Object value = table.get( key ); - if( value instanceof Number ) - { - return ((Number) value).doubleValue(); - } - else - { - throw badKey( key, "number", value ); - } - } - public static boolean getBooleanField( @Nonnull Map table, @Nonnull String key ) throws LuaException { Object value = table.get( key ); @@ -119,6 +109,23 @@ public final class TableHelper } } + public static double optNumberField( @Nonnull Map table, @Nonnull String key, double def ) throws LuaException + { + Object value = table.get( key ); + if( value == null ) + { + return def; + } + else if( value instanceof Number ) + { + return ((Number) value).doubleValue(); + } + else + { + throw badKey( key, "number", value ); + } + } + public static int optIntField( @Nonnull Map table, @Nonnull String key, int def ) throws LuaException { Object value = table.get( key ); @@ -141,23 +148,6 @@ public final class TableHelper return checkReal( key, optNumberField( table, key, def ) ); } - public static double optNumberField( @Nonnull Map table, @Nonnull String key, double def ) throws LuaException - { - Object value = table.get( key ); - if( value == null ) - { - return def; - } - else if( value instanceof Number ) - { - return ((Number) value).doubleValue(); - } - else - { - throw badKey( key, "number", value ); - } - } - public static boolean optBooleanField( @Nonnull Map table, @Nonnull String key, boolean def ) throws LuaException { Object value = table.get( key ); @@ -209,4 +199,10 @@ public final class TableHelper throw badKey( key, "table", value ); } } + + private static double checkReal( @Nonnull String key, double value ) throws LuaException + { + if( !Double.isFinite( value ) ) throw badKey( key, "number", getNumericType( value ) ); + return value; + } } diff --git a/src/main/java/dan200/computercraft/core/apis/TermAPI.java b/src/main/java/dan200/computercraft/core/apis/TermAPI.java index b081e2ee9..6b1816096 100644 --- a/src/main/java/dan200/computercraft/core/apis/TermAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/TermAPI.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; import dan200.computercraft.api.lua.IArguments; @@ -28,7 +27,7 @@ public class TermAPI extends TermMethods implements ILuaAPI public TermAPI( IAPIEnvironment environment ) { - this.terminal = environment.getTerminal(); + terminal = environment.getTerminal(); this.environment = environment.getComputerEnvironment(); } @@ -49,10 +48,7 @@ public class TermAPI extends TermMethods implements ILuaAPI * @cc.treturn number The blue channel, will be between 0 and 1. * @see TermMethods#setPaletteColour(IArguments) To change the palette colour. */ - @LuaFunction( { - "nativePaletteColour", - "nativePaletteColor" - } ) + @LuaFunction( { "nativePaletteColour", "nativePaletteColor" } ) public final Object[] nativePaletteColour( int colour ) throws LuaException { int actualColour = 15 - parseColour( colour ); @@ -61,10 +57,7 @@ public class TermAPI extends TermMethods implements ILuaAPI float[] rgb = c.getRGB(); Object[] rgbObj = new Object[rgb.length]; - for( int i = 0; i < rgbObj.length; ++i ) - { - rgbObj[i] = rgb[i]; - } + for( int i = 0; i < rgbObj.length; ++i ) rgbObj[i] = rgb[i]; return rgbObj; } @@ -72,12 +65,12 @@ public class TermAPI extends TermMethods implements ILuaAPI @Override public Terminal getTerminal() { - return this.terminal; + return terminal; } @Override public boolean isColour() { - return this.environment.isColour(); + return environment.isColour(); } } diff --git a/src/main/java/dan200/computercraft/core/apis/TermMethods.java b/src/main/java/dan200/computercraft/core/apis/TermMethods.java index a3d959844..ce5545124 100644 --- a/src/main/java/dan200/computercraft/core/apis/TermMethods.java +++ b/src/main/java/dan200/computercraft/core/apis/TermMethods.java @@ -22,10 +22,27 @@ import javax.annotation.Nonnull; */ public abstract class TermMethods { + private static int getHighestBit( int group ) + { + int bit = 0; + while( group > 0 ) + { + group >>= 1; + bit++; + } + return bit; + } + + @Nonnull + public abstract Terminal getTerminal() throws LuaException; + + public abstract boolean isColour() throws LuaException; + /** * Write {@code text} at the current cursor position, moving the cursor to the end of the text. * - * Unlike functions like {@code write} and {@code print}, this does not wrap the text - it simply copies the text to the current terminal line. + * Unlike functions like {@code write} and {@code print}, this does not wrap the text - it simply copies the + * text to the current terminal line. * * @param arguments The text to write. * @throws LuaException (hidden) If the terminal cannot be found. @@ -35,7 +52,7 @@ public abstract class TermMethods public final void write( IArguments arguments ) throws LuaException { String text = StringUtil.toString( arguments.get( 0 ) ); - Terminal terminal = this.getTerminal(); + Terminal terminal = getTerminal(); synchronized( terminal ) { terminal.write( text ); @@ -43,14 +60,11 @@ public abstract class TermMethods } } - @Nonnull - public abstract Terminal getTerminal() throws LuaException; - /** * Move all positions up (or down) by {@code y} pixels. * - * Every pixel in the terminal will be replaced by the line {@code y} pixels below it. If {@code y} is negative, it will copy pixels from above - * instead. + * Every pixel in the terminal will be replaced by the line {@code y} pixels below it. If {@code y} is negative, it + * will copy pixels from above instead. * * @param y The number of lines to move up by. This may be a negative number. * @throws LuaException (hidden) If the terminal cannot be found. @@ -58,7 +72,7 @@ public abstract class TermMethods @LuaFunction public final void scroll( int y ) throws LuaException { - this.getTerminal().scroll( y ); + getTerminal().scroll( y ); } /** @@ -72,11 +86,8 @@ public abstract class TermMethods @LuaFunction public final Object[] getCursorPos() throws LuaException { - Terminal terminal = this.getTerminal(); - return new Object[] { - terminal.getCursorX() + 1, - terminal.getCursorY() + 1 - }; + Terminal terminal = getTerminal(); + return new Object[] { terminal.getCursorX() + 1, terminal.getCursorY() + 1 }; } /** @@ -89,7 +100,7 @@ public abstract class TermMethods @LuaFunction public final void setCursorPos( int x, int y ) throws LuaException { - Terminal terminal = this.getTerminal(); + Terminal terminal = getTerminal(); synchronized( terminal ) { terminal.setCursorPos( x - 1, y - 1 ); @@ -105,7 +116,7 @@ public abstract class TermMethods @LuaFunction public final boolean getCursorBlink() throws LuaException { - return this.getTerminal().getCursorBlink(); + return getTerminal().getCursorBlink(); } /** @@ -117,7 +128,7 @@ public abstract class TermMethods @LuaFunction public final void setCursorBlink( boolean blink ) throws LuaException { - Terminal terminal = this.getTerminal(); + Terminal terminal = getTerminal(); synchronized( terminal ) { terminal.setCursorBlink( blink ); @@ -135,11 +146,8 @@ public abstract class TermMethods @LuaFunction public final Object[] getSize() throws LuaException { - Terminal terminal = this.getTerminal(); - return new Object[] { - terminal.getWidth(), - terminal.getHeight() - }; + Terminal terminal = getTerminal(); + return new Object[] { terminal.getWidth(), terminal.getHeight() }; } /** @@ -150,18 +158,19 @@ public abstract class TermMethods @LuaFunction public final void clear() throws LuaException { - this.getTerminal().clear(); + getTerminal().clear(); } /** - * Clears the line the cursor is currently on, filling it with the {@link #getBackgroundColour() current background colour}. + * Clears the line the cursor is currently on, filling it with the {@link #getBackgroundColour() current background + * colour}. * * @throws LuaException (hidden) If the terminal cannot be found. */ @LuaFunction public final void clearLine() throws LuaException { - this.getTerminal().clearLine(); + getTerminal().clearLine(); } /** @@ -171,13 +180,10 @@ public abstract class TermMethods * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants, returned by this function. */ - @LuaFunction( { - "getTextColour", - "getTextColor" - } ) + @LuaFunction( { "getTextColour", "getTextColor" } ) public final int getTextColour() throws LuaException { - return encodeColour( this.getTerminal().getTextColour() ); + return encodeColour( getTerminal().getTextColour() ); } /** @@ -187,81 +193,44 @@ public abstract class TermMethods * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants. */ - @LuaFunction( { - "setTextColour", - "setTextColor" - } ) + @LuaFunction( { "setTextColour", "setTextColor" } ) public final void setTextColour( int colourArg ) throws LuaException { int colour = parseColour( colourArg ); - Terminal terminal = this.getTerminal(); + Terminal terminal = getTerminal(); synchronized( terminal ) { terminal.setTextColour( colour ); } } - public static int parseColour( int colour ) throws LuaException - { - if( colour <= 0 ) - { - throw new LuaException( "Colour out of range" ); - } - colour = getHighestBit( colour ) - 1; - if( colour < 0 || colour > 15 ) - { - throw new LuaException( "Colour out of range" ); - } - return colour; - } - - private static int getHighestBit( int group ) - { - int bit = 0; - while( group > 0 ) - { - group >>= 1; - bit++; - } - return bit; - } - - public static int encodeColour( int colour ) - { - return 1 << colour; - } - /** - * Return the current background colour. This is used when {@link #write writing text} and {@link #clear clearing} the terminal. + * Return the current background colour. This is used when {@link #write writing text} and {@link #clear clearing} + * the terminal. * * @return The current background colour. * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants, returned by this function. */ - @LuaFunction( { - "getBackgroundColour", - "getBackgroundColor" - } ) + @LuaFunction( { "getBackgroundColour", "getBackgroundColor" } ) public final int getBackgroundColour() throws LuaException { - return encodeColour( this.getTerminal().getBackgroundColour() ); + return encodeColour( getTerminal().getBackgroundColour() ); } /** - * Set the current background colour. This is used when {@link #write writing text} and {@link #clear clearing} the terminal. + * Set the current background colour. This is used when {@link #write writing text} and {@link #clear clearing} the + * terminal. * * @param colourArg The new background colour. * @throws LuaException (hidden) If the terminal cannot be found. * @cc.see colors For a list of colour constants. */ - @LuaFunction( { - "setBackgroundColour", - "setBackgroundColor" - } ) + @LuaFunction( { "setBackgroundColour", "setBackgroundColor" } ) public final void setBackgroundColour( int colourArg ) throws LuaException { int colour = parseColour( colourArg ); - Terminal terminal = this.getTerminal(); + Terminal terminal = getTerminal(); synchronized( terminal ) { terminal.setBackgroundColour( colour ); @@ -271,29 +240,27 @@ public abstract class TermMethods /** * Determine if this terminal supports colour. * - * Terminals which do not support colour will still allow writing coloured text/backgrounds, but it will be displayed in greyscale. + * Terminals which do not support colour will still allow writing coloured text/backgrounds, but it will be + * displayed in greyscale. * * @return Whether this terminal supports colour. * @throws LuaException (hidden) If the terminal cannot be found. */ - @LuaFunction( { - "isColour", - "isColor" - } ) + @LuaFunction( { "isColour", "isColor" } ) public final boolean getIsColour() throws LuaException { - return this.isColour(); + return isColour(); } - public abstract boolean isColour() throws LuaException; - /** * Writes {@code text} to the terminal with the specific foreground and background characters. * - * As with {@link #write(IArguments)}, the text will be written at the current cursor location, with the cursor moving to the end of the text. + * As with {@link #write(IArguments)}, the text will be written at the current cursor location, with the cursor + * moving to the end of the text. * - * {@code textColour} and {@code backgroundColour} must both be strings the same length as {@code text}. All characters represent a single hexadecimal - * digit, which is converted to one of CC's colours. For instance, {@code "a"} corresponds to purple. + * {@code textColour} and {@code backgroundColour} must both be strings the same length as {@code text}. All + * characters represent a single hexadecimal digit, which is converted to one of CC's colours. For instance, + * {@code "a"} corresponds to purple. * * @param text The text to write. * @param textColour The corresponding text colours. @@ -302,8 +269,8 @@ public abstract class TermMethods * @cc.see colors For a list of colour constants, and their hexadecimal values. * @cc.usage Prints "Hello, world!" in rainbow text. *
    {@code
    -     *     term.blit("Hello, world!","01234456789ab","0000000000000")
    -     *     }
    + * term.blit("Hello, world!","01234456789ab","0000000000000") + * } */ @LuaFunction public final void blit( String text, String textColour, String backgroundColour ) throws LuaException @@ -313,7 +280,7 @@ public abstract class TermMethods throw new LuaException( "Arguments must be the same length" ); } - Terminal terminal = this.getTerminal(); + Terminal terminal = getTerminal(); synchronized( terminal ) { terminal.blit( text, textColour, backgroundColour ); @@ -324,38 +291,36 @@ public abstract class TermMethods /** * Set the palette for a specific colour. * - * ComputerCraft's palette system allows you to change how a specific colour should be displayed. For instance, you can make @{colors.red} more - * red by setting its palette to #FF0000. This does now allow you to draw more colours - you are still limited to 16 on the screen at one time - - * but you can change which colours are used. + * ComputerCraft's palette system allows you to change how a specific colour should be displayed. For instance, you + * can make @{colors.red} more red by setting its palette to #FF0000. This does now allow you to draw more + * colours - you are still limited to 16 on the screen at one time - but you can change which colours are + * used. * * @param args The new palette values. * @throws LuaException (hidden) If the terminal cannot be found. * @cc.tparam [1] number index The colour whose palette should be changed. - * @cc.tparam number colour A 24-bit integer representing the RGB value of the colour. For instance the integer `0xFF0000` corresponds to the colour - * #FF0000. + * @cc.tparam number colour A 24-bit integer representing the RGB value of the colour. For instance the integer + * `0xFF0000` corresponds to the colour #FF0000. * @cc.tparam [2] number index The colour whose palette should be changed. * @cc.tparam number r The intensity of the red channel, between 0 and 1. * @cc.tparam number g The intensity of the green channel, between 0 and 1. * @cc.tparam number b The intensity of the blue channel, between 0 and 1. * @cc.usage Change the @{colors.red|red colour} from the default #CC4C4C to #FF0000. *
    {@code
    -     *     term.setPaletteColour(colors.red, 0xFF0000)
    -     *     term.setTextColour(colors.red)
    -     *     print("Hello, world!")
    -     *     }
    + * term.setPaletteColour(colors.red, 0xFF0000) + * term.setTextColour(colors.red) + * print("Hello, world!") + * } * @cc.usage As above, but specifying each colour channel separately. *
    {@code
    -     *     term.setPaletteColour(colors.red, 1, 0, 0)
    -     *     term.setTextColour(colors.red)
    -     *     print("Hello, world!")
    -     *     }
    + * term.setPaletteColour(colors.red, 1, 0, 0) + * term.setTextColour(colors.red) + * print("Hello, world!") + * } * @cc.see colors.unpackRGB To convert from the 24-bit format to three separate channels. * @cc.see colors.packRGB To convert from three separate channels to the 24-bit format. */ - @LuaFunction( { - "setPaletteColour", - "setPaletteColor" - } ) + @LuaFunction( { "setPaletteColour", "setPaletteColor" } ) public final void setPaletteColour( IArguments args ) throws LuaException { int colour = 15 - parseColour( args.getInt( 0 ) ); @@ -363,24 +328,17 @@ public abstract class TermMethods { int hex = args.getInt( 1 ); double[] rgb = Palette.decodeRGB8( hex ); - setColour( this.getTerminal(), colour, rgb[0], rgb[1], rgb[2] ); + setColour( getTerminal(), colour, rgb[0], rgb[1], rgb[2] ); } else { double r = args.getFiniteDouble( 1 ); double g = args.getFiniteDouble( 2 ); double b = args.getFiniteDouble( 3 ); - setColour( this.getTerminal(), colour, r, g, b ); + setColour( getTerminal(), colour, r, g, b ); } } - public static void setColour( Terminal terminal, int colour, double r, double g, double b ) - { - terminal.getPalette() - .setColour( colour, r, g, b ); - terminal.setChanged(); - } - /** * Get the current palette for a specific colour. * @@ -391,18 +349,34 @@ public abstract class TermMethods * @cc.treturn number The green channel, will be between 0 and 1. * @cc.treturn number The blue channel, will be between 0 and 1. */ - @LuaFunction( { - "getPaletteColour", - "getPaletteColor" - } ) + @LuaFunction( { "getPaletteColour", "getPaletteColor" } ) public final Object[] getPaletteColour( int colourArg ) throws LuaException { int colour = 15 - parseColour( colourArg ); - Terminal terminal = this.getTerminal(); + Terminal terminal = getTerminal(); synchronized( terminal ) { - return ArrayUtils.toObject( terminal.getPalette() - .getColour( colour ) ); + return ArrayUtils.toObject( terminal.getPalette().getColour( colour ) ); } } + + public static int parseColour( int colour ) throws LuaException + { + if( colour <= 0 ) throw new LuaException( "Colour out of range" ); + colour = getHighestBit( colour ) - 1; + if( colour < 0 || colour > 15 ) throw new LuaException( "Colour out of range" ); + return colour; + } + + + public static int encodeColour( int colour ) + { + return 1 << colour; + } + + public static void setColour( Terminal terminal, int colour, double r, double g, double b ) + { + terminal.getPalette().setColour( colour, r, g, b ); + terminal.setChanged(); + } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java b/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java index e1c9ddec7..d3313b1fc 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java +++ b/src/main/java/dan200/computercraft/core/apis/http/CheckUrl.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http; import dan200.computercraft.core.apis.IAPIEnvironment; @@ -20,10 +19,12 @@ import java.util.concurrent.Future; public class CheckUrl extends Resource { private static final String EVENT = "http_check"; + + private Future future; + private final IAPIEnvironment environment; private final String address; private final URI uri; - private Future future; public CheckUrl( ResourceGroup limiter, IAPIEnvironment environment, String address, URI uri ) { @@ -35,20 +36,14 @@ public class CheckUrl extends Resource public void run() { - if( this.isClosed() ) - { - return; - } - this.future = NetworkUtils.EXECUTOR.submit( this::doRun ); - this.checkClosed(); + if( isClosed() ) return; + future = NetworkUtils.EXECUTOR.submit( this::doRun ); + checkClosed(); } private void doRun() { - if( this.isClosed() ) - { - return; - } + if( isClosed() ) return; try { @@ -56,17 +51,11 @@ public class CheckUrl extends Resource InetSocketAddress netAddress = NetworkUtils.getAddress( uri, ssl ); NetworkUtils.getOptions( uri.getHost(), netAddress ); - if( this.tryClose() ) - { - this.environment.queueEvent( EVENT, this.address, true ); - } + if( tryClose() ) environment.queueEvent( EVENT, address, true ); } catch( HTTPRequestException e ) { - if( this.tryClose() ) - { - this.environment.queueEvent( EVENT, this.address, false, e.getMessage() ); - } + if( tryClose() ) environment.queueEvent( EVENT, address, false, e.getMessage() ); } } @@ -74,6 +63,6 @@ public class CheckUrl extends Resource protected void dispose() { super.dispose(); - this.future = closeFuture( this.future ); + future = closeFuture( future ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java b/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java index ea1864ab6..abf0cdabc 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java +++ b/src/main/java/dan200/computercraft/core/apis/http/HTTPRequestException.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http; public class HTTPRequestException extends Exception diff --git a/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java b/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java index 4e2539aeb..f3804f847 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java +++ b/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http; import dan200.computercraft.ComputerCraft; @@ -12,12 +11,19 @@ import dan200.computercraft.core.apis.http.options.AddressRule; import dan200.computercraft.core.apis.http.options.Options; import dan200.computercraft.shared.util.ThreadUtils; import io.netty.buffer.ByteBuf; +import io.netty.channel.ConnectTimeoutException; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.handler.codec.DecoderException; +import io.netty.handler.codec.TooLongFrameException; +import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.timeout.ReadTimeoutException; +import javax.annotation.Nonnull; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManagerFactory; import java.net.InetSocketAddress; import java.net.URI; @@ -32,69 +38,35 @@ import java.util.concurrent.TimeUnit; */ public final class NetworkUtils { - public static final ExecutorService EXECUTOR = new ThreadPoolExecutor( 4, - Integer.MAX_VALUE, - 60L, - TimeUnit.SECONDS, + public static final ExecutorService EXECUTOR = new ThreadPoolExecutor( + 4, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), ThreadUtils.builder( "Network" ) .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 ) - .build() ); + .build() + ); - public static final EventLoopGroup LOOP_GROUP = new NioEventLoopGroup( 4, - ThreadUtils.builder( "Netty" ) - .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 ) - .build() ); - private static final Object sslLock = new Object(); - private static TrustManagerFactory trustManager; - private static SslContext sslContext; - private static boolean triedSslContext = false; + public static final EventLoopGroup LOOP_GROUP = new NioEventLoopGroup( 4, ThreadUtils.builder( "Netty" ) + .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 ) + .build() + ); private NetworkUtils() { } - public static SslContext getSslContext() throws HTTPRequestException - { - if( sslContext != null || triedSslContext ) - { - return sslContext; - } - synchronized( sslLock ) - { - if( sslContext != null || triedSslContext ) - { - return sslContext; - } - try - { - return sslContext = SslContextBuilder.forClient() - .trustManager( getTrustManager() ) - .build(); - } - catch( SSLException e ) - { - ComputerCraft.log.error( "Cannot construct SSL context", e ); - triedSslContext = true; - sslContext = null; - - throw new HTTPRequestException( "Cannot create a secure connection" ); - } - } - } + private static final Object sslLock = new Object(); + private static TrustManagerFactory trustManager; + private static SslContext sslContext; + private static boolean triedSslContext = false; private static TrustManagerFactory getTrustManager() { - if( trustManager != null ) - { - return trustManager; - } + if( trustManager != null ) return trustManager; synchronized( sslLock ) { - if( trustManager != null ) - { - return trustManager; - } + if( trustManager != null ) return trustManager; TrustManagerFactory tmf = null; try @@ -111,6 +83,30 @@ public final class NetworkUtils } } + public static SslContext getSslContext() throws HTTPRequestException + { + if( sslContext != null || triedSslContext ) return sslContext; + synchronized( sslLock ) + { + if( sslContext != null || triedSslContext ) return sslContext; + try + { + return sslContext = SslContextBuilder + .forClient() + .trustManager( getTrustManager() ) + .build(); + } + catch( SSLException e ) + { + ComputerCraft.log.error( "Cannot construct SSL context", e ); + triedSslContext = true; + sslContext = null; + + throw new HTTPRequestException( "Cannot create a secure connection" ); + } + } + } + /** * Create a {@link InetSocketAddress} from a {@link java.net.URI}. * @@ -139,15 +135,9 @@ public final class NetworkUtils */ public static InetSocketAddress getAddress( String host, int port, boolean ssl ) throws HTTPRequestException { - if( port < 0 ) - { - port = ssl ? 443 : 80; - } + if( port < 0 ) port = ssl ? 443 : 80; InetSocketAddress socketAddress = new InetSocketAddress( host, port ); - if( socketAddress.isUnresolved() ) - { - throw new HTTPRequestException( "Unknown host" ); - } + if( socketAddress.isUnresolved() ) throw new HTTPRequestException( "Unknown host" ); return socketAddress; } @@ -162,10 +152,7 @@ public final class NetworkUtils public static Options getOptions( String host, InetSocketAddress address ) throws HTTPRequestException { Options options = AddressRule.apply( ComputerCraft.httpRules, host, address ); - if( options.action == Action.DENY ) - { - throw new HTTPRequestException( "Domain not permitted" ); - } + if( options.action == Action.DENY ) throw new HTTPRequestException( "Domain not permitted" ); return options; } @@ -181,4 +168,29 @@ public final class NetworkUtils buffer.readBytes( bytes ); return bytes; } + + @Nonnull + public static String toFriendlyError( @Nonnull Throwable cause ) + { + if( cause instanceof WebSocketHandshakeException || cause instanceof HTTPRequestException ) + { + return cause.getMessage(); + } + else if( cause instanceof TooLongFrameException ) + { + return "Message is too large"; + } + else if( cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException ) + { + return "Timed out"; + } + else if( cause instanceof SSLHandshakeException || (cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException) ) + { + return "Could not create a secure connection"; + } + else + { + return "Could not connect"; + } + } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/Resource.java b/src/main/java/dan200/computercraft/core/apis/http/Resource.java index 1c16cc050..142fb1dca 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/Resource.java +++ b/src/main/java/dan200/computercraft/core/apis/http/Resource.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http; import dan200.computercraft.shared.util.IoUtil; @@ -25,7 +24,6 @@ import java.util.function.Consumer; */ public abstract class Resource> implements Closeable { - private static final ReferenceQueue QUEUE = new ReferenceQueue<>(); private final AtomicBoolean closed = new AtomicBoolean( false ); private final ResourceGroup limiter; @@ -34,66 +32,6 @@ public abstract class Resource> implements Closeable this.limiter = limiter; } - protected static T closeCloseable( T closeable ) - { - IoUtil.closeQuietly( closeable ); - return null; - } - - protected static ChannelFuture closeChannel( ChannelFuture future ) - { - if( future != null ) - { - future.cancel( false ); - Channel channel = future.channel(); - if( channel != null && channel.isOpen() ) - { - channel.close(); - } - } - - return null; - } - - protected static > T closeFuture( T future ) - { - if( future != null ) - { - future.cancel( true ); - } - return null; - } - - public static void cleanup() - { - Reference reference; - while( (reference = QUEUE.poll()) != null ) - { - ((CloseReference) reference).resource.close(); - } - } - - @Override - public final void close() - { - this.tryClose(); - } - - /** - * Try to close the current resource. - * - * @return Whether this was successfully closed, or {@code false} if it has already been closed. - */ - protected final boolean tryClose() - { - if( this.closed.getAndSet( true ) ) - { - return false; - } - this.dispose(); - return true; - } - /** * Whether this resource is closed. * @@ -101,7 +39,7 @@ public abstract class Resource> implements Closeable */ public final boolean isClosed() { - return this.closed.get(); + return closed.get(); } /** @@ -111,24 +49,34 @@ public abstract class Resource> implements Closeable */ public final boolean checkClosed() { - if( !this.closed.get() ) - { - return false; - } - this.dispose(); + if( !closed.get() ) return false; + dispose(); + return true; + } + + /** + * Try to close the current resource. + * + * @return Whether this was successfully closed, or {@code false} if it has already been closed. + */ + protected final boolean tryClose() + { + if( closed.getAndSet( true ) ) return false; + dispose(); return true; } /** * Clean up any pending resources * - * Note, this may be called multiple times, and so should be thread-safe and avoid any major side effects. + * Note, this may be called multiple times, and so should be thread-safe and + * avoid any major side effects. */ protected void dispose() { @SuppressWarnings( "unchecked" ) T thisT = (T) this; - this.limiter.release( thisT ); + limiter.release( thisT ); } /** @@ -143,13 +91,46 @@ public abstract class Resource> implements Closeable return new CloseReference<>( this, object ); } - public boolean queue( Consumer task ) + @Override + public final void close() + { + tryClose(); + } + + public final boolean queue( Consumer task ) { @SuppressWarnings( "unchecked" ) T thisT = (T) this; - return this.limiter.queue( thisT, () -> task.accept( thisT ) ); + return limiter.queue( thisT, () -> task.accept( thisT ) ); } + protected static T closeCloseable( T closeable ) + { + IoUtil.closeQuietly( closeable ); + return null; + } + + protected static ChannelFuture closeChannel( ChannelFuture future ) + { + if( future != null ) + { + future.cancel( false ); + Channel channel = future.channel(); + if( channel != null && channel.isOpen() ) channel.close(); + } + + return null; + } + + protected static > T closeFuture( T future ) + { + if( future != null ) future.cancel( true ); + return null; + } + + + private static final ReferenceQueue QUEUE = new ReferenceQueue<>(); + private static class CloseReference extends WeakReference { final Resource resource; @@ -160,4 +141,10 @@ public abstract class Resource> implements Closeable this.resource = resource; } } + + public static void cleanup() + { + Reference reference; + while( (reference = QUEUE.poll()) != null ) ((CloseReference) reference).resource.close(); + } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java b/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java index 058c9875f..8411eebbe 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java +++ b/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http; import java.util.Collections; @@ -19,12 +18,17 @@ import java.util.function.Supplier; */ public class ResourceGroup> { + public static final int DEFAULT_LIMIT = 512; + public static final IntSupplier DEFAULT = () -> DEFAULT_LIMIT; + private static final IntSupplier ZERO = () -> 0; final IntSupplier limit; - final Set resources = Collections.newSetFromMap( new ConcurrentHashMap<>() ); + boolean active = false; + final Set resources = Collections.newSetFromMap( new ConcurrentHashMap<>() ); + public ResourceGroup( IntSupplier limit ) { this.limit = limit; @@ -32,23 +36,20 @@ public class ResourceGroup> public ResourceGroup() { - this.limit = ZERO; + limit = ZERO; } public void startup() { - this.active = true; + active = true; } public synchronized void shutdown() { - this.active = false; + active = false; - for( T resource : this.resources ) - { - resource.close(); - } - this.resources.clear(); + for( T resource : resources ) resource.close(); + resources.clear(); Resource.cleanup(); } @@ -56,7 +57,7 @@ public class ResourceGroup> public final boolean queue( T resource, Runnable setup ) { - return this.queue( () -> { + return queue( () -> { setup.run(); return resource; } ); @@ -65,15 +66,12 @@ public class ResourceGroup> public synchronized boolean queue( Supplier resource ) { Resource.cleanup(); - if( !this.active ) - { - return false; - } + if( !active ) return false; int limit = this.limit.getAsInt(); - if( limit <= 0 || this.resources.size() < limit ) + if( limit <= 0 || resources.size() < limit ) { - this.resources.add( resource.get() ); + resources.add( resource.get() ); return true; } @@ -82,6 +80,6 @@ public class ResourceGroup> public synchronized void release( T resource ) { - this.resources.remove( resource ); + resources.remove( resource ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java b/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java index 74c79ce53..0b79c8f5e 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java +++ b/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http; import java.util.ArrayDeque; @@ -32,21 +31,17 @@ public class ResourceQueue> extends ResourceGroup public synchronized void shutdown() { super.shutdown(); - this.pending.clear(); + pending.clear(); } @Override public synchronized boolean queue( Supplier resource ) { - if( !this.active ) - { - return false; - } + if( !active ) return false; + if( super.queue( resource ) ) return true; + if( pending.size() > DEFAULT_LIMIT ) return false; - if( !super.queue( resource ) ) - { - this.pending.add( resource ); - } + pending.add( resource ); return true; } @@ -55,19 +50,13 @@ public class ResourceQueue> extends ResourceGroup { super.release( resource ); - if( !this.active ) - { - return; - } + if( !active ) return; int limit = this.limit.getAsInt(); - if( limit <= 0 || this.resources.size() < limit ) + if( limit <= 0 || resources.size() < limit ) { - Supplier next = this.pending.poll(); - if( next != null ) - { - this.resources.add( next.get() ); - } + Supplier next = pending.poll(); + if( next != null ) resources.add( next.get() ); } } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/Action.java b/src/main/java/dan200/computercraft/core/apis/http/options/Action.java index df8641a2f..f994ec3a3 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/options/Action.java +++ b/src/main/java/dan200/computercraft/core/apis/http/options/Action.java @@ -9,13 +9,14 @@ import javax.annotation.Nonnull; public enum Action { - ALLOW, DENY; + ALLOW, + DENY; private final PartialOptions partial = new PartialOptions( this, null, null, null, null ); @Nonnull public PartialOptions toPartial() { - return this.partial; + return partial; } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java index 912e8e057..955e89d4d 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java +++ b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http.options; import com.google.common.net.InetAddresses; @@ -62,6 +61,23 @@ public final class AddressRule } } + /** + * Determine whether the given address matches a series of patterns. + * + * @param domain The domain to match + * @param port The port of the address. + * @param address The address to check. + * @param ipv4Address An ipv4 version of the address, if the original was an ipv6 address. + * @return Whether it matches any of these patterns. + */ + private boolean matches( String domain, int port, InetAddress address, Inet4Address ipv4Address ) + { + if( this.port != null && this.port != port ) return false; + return predicate.matches( domain ) + || predicate.matches( address ) + || (ipv4Address != null && predicate.matches( ipv4Address )); + } + public static Options apply( Iterable rules, String domain, InetSocketAddress socketAddress ) { PartialOptions options = null; @@ -95,21 +111,4 @@ public final class AddressRule return (options == null ? PartialOptions.DEFAULT : options).toOptions(); } - - /** - * Determine whether the given address matches a series of patterns. - * - * @param domain The domain to match - * @param port The port of the address. - * @param address The address to check. - * @param ipv4Address An ipv4 version of the address, if the original was an ipv6 address. - * @return Whether it matches any of these patterns. - */ - private boolean matches( String domain, int port, InetAddress address, Inet4Address ipv4Address ) - { - if( this.port != null && this.port != port ) return false; - return predicate.matches( domain ) - || predicate.matches( address ) - || (ipv4Address != null && predicate.matches( ipv4Address )); - } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java index 3fb2c6e6f..862ff39b6 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java +++ b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java @@ -5,8 +5,8 @@ */ package dan200.computercraft.core.apis.http.options; - import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.Config; import com.electronwill.nightconfig.core.InMemoryCommentedFormat; import com.electronwill.nightconfig.core.UnmodifiableConfig; import dan200.computercraft.ComputerCraft; @@ -16,10 +16,11 @@ import java.util.Locale; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; - +/** + * Parses, checks and generates {@link Config}s for {@link AddressRule}. + */ public class AddressRuleConfig { - public static UnmodifiableConfig makeRule( String host, Action action ) { CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new ); @@ -61,10 +62,10 @@ public class AddressRuleConfig public static AddressRule parseRule( UnmodifiableConfig builder ) { String hostObj = get( builder, "host", String.class ).orElse( null ); - Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null ); if( hostObj == null ) return null; Action action = getEnum( builder, "action", Action.class ).orElse( null ); + Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null ); Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null ); Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null ); Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null ); diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java b/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java index 76699aa30..ef0801966 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java +++ b/src/main/java/dan200/computercraft/core/apis/http/options/PartialOptions.java @@ -31,43 +31,28 @@ public final class PartialOptions @Nonnull Options toOptions() { - if( this.options != null ) - { - return this.options; - } + if( options != null ) return options; - return this.options = new Options( this.action == null ? Action.DENY : this.action, - this.maxUpload == null ? AddressRule.MAX_UPLOAD : this.maxUpload, - this.maxDownload == null ? AddressRule.MAX_DOWNLOAD : this.maxDownload, - this.timeout == null ? AddressRule.TIMEOUT : this.timeout, this.websocketMessage == null ? AddressRule.WEBSOCKET_MESSAGE : this.websocketMessage ); + return options = new Options( + action == null ? Action.DENY : action, + maxUpload == null ? AddressRule.MAX_UPLOAD : maxUpload, + maxDownload == null ? AddressRule.MAX_DOWNLOAD : maxDownload, + timeout == null ? AddressRule.TIMEOUT : timeout, + websocketMessage == null ? AddressRule.WEBSOCKET_MESSAGE : websocketMessage + ); } void merge( @Nonnull PartialOptions other ) { - if( this.action == null && other.action != null ) - { - this.action = other.action; - } - if( this.maxUpload == null && other.maxUpload != null ) - { - this.maxUpload = other.maxUpload; - } - if( this.maxDownload == null && other.maxDownload != null ) - { - this.maxDownload = other.maxDownload; - } - if( this.timeout == null && other.timeout != null ) - { - this.timeout = other.timeout; - } - if( this.websocketMessage == null && other.websocketMessage != null ) - { - this.websocketMessage = other.websocketMessage; - } + if( action == null && other.action != null ) action = other.action; + if( maxUpload == null && other.maxUpload != null ) maxUpload = other.maxUpload; + if( maxDownload == null && other.maxDownload != null ) maxDownload = other.maxDownload; + if( timeout == null && other.timeout != null ) timeout = other.timeout; + if( websocketMessage == null && other.websocketMessage != null ) websocketMessage = other.websocketMessage; } PartialOptions copy() { - return new PartialOptions( this.action, this.maxUpload, this.maxDownload, this.timeout, this.websocketMessage ); + return new PartialOptions( action, maxUpload, maxDownload, timeout, websocketMessage ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java index b6ba95a21..2049575ff 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java +++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http.request; import dan200.computercraft.ComputerCraft; @@ -20,13 +19,10 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; -import io.netty.channel.ConnectTimeoutException; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.TooLongFrameException; import io.netty.handler.codec.http.*; import io.netty.handler.ssl.SslContext; -import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import java.net.InetSocketAddress; @@ -48,26 +44,31 @@ public class HttpRequest extends Resource private static final String FAILURE_EVENT = "http_failure"; private static final int MAX_REDIRECTS = 16; - final AtomicInteger redirects; - private final IAPIEnvironment environment; - private final String address; - private final ByteBuf postBuffer; - private final HttpHeaders headers; - private final boolean binary; + private Future executorFuture; private ChannelFuture connectFuture; private HttpRequestHandler currentRequest; - public HttpRequest( ResourceGroup limiter, IAPIEnvironment environment, String address, String postText, HttpHeaders headers, - boolean binary, boolean followRedirects ) + private final IAPIEnvironment environment; + + private final String address; + private final ByteBuf postBuffer; + private final HttpHeaders headers; + private final boolean binary; + + final AtomicInteger redirects; + + public HttpRequest( ResourceGroup limiter, IAPIEnvironment environment, String address, String postText, HttpHeaders headers, boolean binary, boolean followRedirects ) { super( limiter ); this.environment = environment; this.address = address; - this.postBuffer = postText != null ? Unpooled.wrappedBuffer( postText.getBytes( StandardCharsets.UTF_8 ) ) : Unpooled.buffer( 0 ); + postBuffer = postText != null + ? Unpooled.wrappedBuffer( postText.getBytes( StandardCharsets.UTF_8 ) ) + : Unpooled.buffer( 0 ); this.headers = headers; this.binary = binary; - this.redirects = new AtomicInteger( followRedirects ? MAX_REDIRECTS : 0 ); + redirects = new AtomicInteger( followRedirects ? MAX_REDIRECTS : 0 ); if( postText != null ) { @@ -78,11 +79,16 @@ public class HttpRequest extends Resource if( !headers.contains( HttpHeaderNames.CONTENT_LENGTH ) ) { - headers.set( HttpHeaderNames.CONTENT_LENGTH, this.postBuffer.readableBytes() ); + headers.set( HttpHeaderNames.CONTENT_LENGTH, postBuffer.readableBytes() ); } } } + public IAPIEnvironment environment() + { + return environment; + } + public static URI checkUri( String address ) throws HTTPRequestException { URI url; @@ -102,73 +108,52 @@ public class HttpRequest extends Resource public static void checkUri( URI url ) throws HTTPRequestException { // Validate the URL - if( url.getScheme() == null ) - { - throw new HTTPRequestException( "Must specify http or https" ); - } - if( url.getHost() == null ) - { - throw new HTTPRequestException( "URL malformed" ); - } + if( url.getScheme() == null ) throw new HTTPRequestException( "Must specify http or https" ); + if( url.getHost() == null ) throw new HTTPRequestException( "URL malformed" ); - String scheme = url.getScheme() - .toLowerCase( Locale.ROOT ); + String scheme = url.getScheme().toLowerCase( Locale.ROOT ); if( !scheme.equalsIgnoreCase( "http" ) && !scheme.equalsIgnoreCase( "https" ) ) { throw new HTTPRequestException( "Invalid protocol '" + scheme + "'" ); } } - public IAPIEnvironment environment() - { - return this.environment; - } - public void request( URI uri, HttpMethod method ) { - if( this.isClosed() ) - { - return; - } - this.executorFuture = NetworkUtils.EXECUTOR.submit( () -> this.doRequest( uri, method ) ); - this.checkClosed(); + if( isClosed() ) return; + executorFuture = NetworkUtils.EXECUTOR.submit( () -> doRequest( uri, method ) ); + checkClosed(); } private void doRequest( URI uri, HttpMethod method ) { // If we're cancelled, abort. - if( this.isClosed() ) - { - return; - } + if( isClosed() ) return; try { - boolean ssl = uri.getScheme() - .equalsIgnoreCase( "https" ); + boolean ssl = uri.getScheme().equalsIgnoreCase( "https" ); InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl ); Options options = NetworkUtils.getOptions( uri.getHost(), socketAddress ); SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null; // getAddress may have a slight delay, so let's perform another cancellation check. - if( this.isClosed() ) - { - return; - } + if( isClosed() ) return; - long requestBody = getHeaderSize( this.headers ) + this.postBuffer.capacity(); + long requestBody = getHeaderSize( headers ) + postBuffer.capacity(); if( options.maxUpload != 0 && requestBody > options.maxUpload ) { - this.failure( "Request body is too large" ); + failure( "Request body is too large" ); return; } // Add request size to the tracker before opening the connection - this.environment.addTrackingChange( TrackingField.HTTP_REQUESTS, 1 ); - this.environment.addTrackingChange( TrackingField.HTTP_UPLOAD, requestBody ); + environment.addTrackingChange( TrackingField.HTTP_REQUESTS, 1 ); + environment.addTrackingChange( TrackingField.HTTP_UPLOAD, requestBody ); - HttpRequestHandler handler = this.currentRequest = new HttpRequestHandler( this, uri, method, options ); - this.connectFuture = new Bootstrap().group( NetworkUtils.LOOP_GROUP ) + HttpRequestHandler handler = currentRequest = new HttpRequestHandler( this, uri, method, options ); + connectFuture = new Bootstrap() + .group( NetworkUtils.LOOP_GROUP ) .channelFactory( NioSocketChannel::new ) .handler( new ChannelInitializer() { @@ -178,8 +163,7 @@ public class HttpRequest extends Resource if( options.timeout > 0 ) { - ch.config() - .setConnectTimeoutMillis( options.timeout ); + ch.config().setConnectTimeoutMillis( options.timeout ); } ChannelPipeline p = ch.pipeline(); @@ -193,93 +177,46 @@ public class HttpRequest extends Resource p.addLast( new ReadTimeoutHandler( options.timeout, TimeUnit.MILLISECONDS ) ); } - p.addLast( new HttpClientCodec(), new HttpContentDecompressor(), handler ); + p.addLast( + new HttpClientCodec(), + new HttpContentDecompressor(), + handler + ); } } ) .remoteAddress( socketAddress ) .connect() .addListener( c -> { - if( !c.isSuccess() ) - { - this.failure( c.cause() ); - } + if( !c.isSuccess() ) failure( NetworkUtils.toFriendlyError( c.cause() ) ); } ); // Do an additional check for cancellation - this.checkClosed(); + checkClosed(); } catch( HTTPRequestException e ) { - this.failure( e.getMessage() ); + failure( e.getMessage() ); } catch( Exception e ) { - this.failure( "Could not connect" ); - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.error( "Error in HTTP request", e ); - } + failure( NetworkUtils.toFriendlyError( e ) ); + if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error in HTTP request", e ); } } - public static long getHeaderSize( HttpHeaders headers ) - { - long size = 0; - for( Map.Entry header : headers ) - { - size += header.getKey() == null ? 0 : header.getKey() - .length(); - size += header.getValue() == null ? 0 : header.getValue() - .length() + 1; - } - return size; - } - void failure( String message ) { - if( this.tryClose() ) - { - this.environment.queueEvent( FAILURE_EVENT, this.address, message ); - } - } - - void failure( Throwable cause ) - { - String message; - if( cause instanceof HTTPRequestException ) - { - message = cause.getMessage(); - } - else if( cause instanceof TooLongFrameException ) - { - message = "Response is too large"; - } - else if( cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException ) - { - message = "Timed out"; - } - else - { - message = "Could not connect"; - } - - this.failure( message ); + if( tryClose() ) environment.queueEvent( FAILURE_EVENT, address, message ); } void failure( String message, HttpResponseHandle object ) { - if( this.tryClose() ) - { - this.environment.queueEvent( FAILURE_EVENT, this.address, message, object ); - } + if( tryClose() ) environment.queueEvent( FAILURE_EVENT, address, message, object ); } void success( HttpResponseHandle object ) { - if( this.tryClose() ) - { - this.environment.queueEvent( SUCCESS_EVENT, this.address, object ); - } + if( tryClose() ) environment.queueEvent( SUCCESS_EVENT, address, object ); } @Override @@ -287,23 +224,34 @@ public class HttpRequest extends Resource { super.dispose(); - this.executorFuture = closeFuture( this.executorFuture ); - this.connectFuture = closeChannel( this.connectFuture ); - this.currentRequest = closeCloseable( this.currentRequest ); + executorFuture = closeFuture( executorFuture ); + connectFuture = closeChannel( connectFuture ); + currentRequest = closeCloseable( currentRequest ); + } + + public static long getHeaderSize( HttpHeaders headers ) + { + long size = 0; + for( Map.Entry header : headers ) + { + size += header.getKey() == null ? 0 : header.getKey().length(); + size += header.getValue() == null ? 0 : header.getValue().length() + 1; + } + return size; } public ByteBuf body() { - return this.postBuffer; + return postBuffer; } public HttpHeaders headers() { - return this.headers; + return headers; } public boolean isBinary() { - return this.binary; + return binary; } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java index 59e833e4d..4ef42ff44 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java +++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java @@ -183,7 +183,7 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler{@code - * local request = http.get("https://example.computercraft.cc") - * print(textutils.serialize(request.getResponseHeaders())) - * -- => { - * -- [ "Content-Type" ] = "text/plain; charset=utf8", - * -- [ "content-length" ] = 17, - * -- ... - * -- } - * request.close() - * } + * local request = http.get("https://example.tweaked.cc") + * print(textutils.serialize(request.getResponseHeaders())) + * -- => { + * -- [ "Content-Type" ] = "text/plain; charset=utf8", + * -- [ "content-length" ] = 17, + * -- ... + * -- } + * request.close() + * } */ @LuaFunction public final Map getResponseHeaders() { - return this.responseHeaders; + return responseHeaders; } @Override public Iterable getExtra() { - return Collections.singletonList( this.reader ); + return Collections.singletonList( reader ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java index d559fc193..fa1399bb6 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java +++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/Websocket.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http.websocket; import com.google.common.base.Strings; @@ -43,8 +42,8 @@ import java.util.concurrent.Future; public class Websocket extends Resource { /** - * We declare the maximum size to be 2^30 bytes. While messages can be much longer, we set an arbitrary limit as working with larger messages - * (especially within a Lua VM) is absurd. + * We declare the maximum size to be 2^30 bytes. While messages can be much longer, we set an arbitrary limit as + * working with larger messages (especially within a Lua VM) is absurd. */ public static final int MAX_MESSAGE_SIZE = 1 << 30; @@ -52,13 +51,15 @@ public class Websocket extends Resource static final String FAILURE_EVENT = "websocket_failure"; static final String CLOSE_EVENT = "websocket_closed"; static final String MESSAGE_EVENT = "websocket_message"; + + private Future executorFuture; + private ChannelFuture connectFuture; + private WeakReference websocketHandle; + private final IAPIEnvironment environment; private final URI uri; private final String address; private final HttpHeaders headers; - private Future executorFuture; - private ChannelFuture connectFuture; - private WeakReference websocketHandle; public Websocket( ResourceGroup limiter, IAPIEnvironment environment, URI uri, String address, HttpHeaders headers ) { @@ -91,10 +92,7 @@ public class Websocket extends Resource } } - if( uri == null || uri.getHost() == null ) - { - throw new HTTPRequestException( "URL malformed" ); - } + if( uri == null || uri.getHost() == null ) throw new HTTPRequestException( "URL malformed" ); String scheme = uri.getScheme(); if( scheme == null ) @@ -118,38 +116,28 @@ public class Websocket extends Resource public void connect() { - if( this.isClosed() ) - { - return; - } - this.executorFuture = NetworkUtils.EXECUTOR.submit( this::doConnect ); - this.checkClosed(); + if( isClosed() ) return; + executorFuture = NetworkUtils.EXECUTOR.submit( this::doConnect ); + checkClosed(); } private void doConnect() { // If we're cancelled, abort. - if( this.isClosed() ) - { - return; - } + if( isClosed() ) return; try { - boolean ssl = this.uri.getScheme() - .equalsIgnoreCase( "wss" ); - + boolean ssl = uri.getScheme().equalsIgnoreCase( "wss" ); InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl ); - Options options = NetworkUtils.getOptions( this.uri.getHost(), socketAddress ); + Options options = NetworkUtils.getOptions( uri.getHost(), socketAddress ); SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null; // getAddress may have a slight delay, so let's perform another cancellation check. - if( this.isClosed() ) - { - return; - } + if( isClosed() ) return; - this.connectFuture = new Bootstrap().group( NetworkUtils.LOOP_GROUP ) + connectFuture = new Bootstrap() + .group( NetworkUtils.LOOP_GROUP ) .channel( NioSocketChannel.class ) .handler( new ChannelInitializer() { @@ -159,81 +147,65 @@ public class Websocket extends Resource ChannelPipeline p = ch.pipeline(); if( sslContext != null ) { - p.addLast( sslContext.newHandler( ch.alloc(), Websocket.this.uri.getHost(), socketAddress.getPort() ) ); + p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) ); } - WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker( Websocket.this.uri, - WebSocketVersion.V13, - null, - true, - Websocket.this.headers, - options.websocketMessage <= 0 ? MAX_MESSAGE_SIZE : options.websocketMessage ); + WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker( + uri, WebSocketVersion.V13, null, true, headers, + options.websocketMessage <= 0 ? MAX_MESSAGE_SIZE : options.websocketMessage + ); - p.addLast( new HttpClientCodec(), + p.addLast( + new HttpClientCodec(), new HttpObjectAggregator( 8192 ), WebSocketClientCompressionHandler.INSTANCE, - new WebsocketHandler( Websocket.this, handshaker, options ) ); + new WebsocketHandler( Websocket.this, handshaker, options ) + ); } } ) .remoteAddress( socketAddress ) .connect() .addListener( c -> { - if( !c.isSuccess() ) - { - this.failure( c.cause() - .getMessage() ); - } + if( !c.isSuccess() ) failure( NetworkUtils.toFriendlyError( c.cause() ) ); } ); // Do an additional check for cancellation - this.checkClosed(); + checkClosed(); } catch( HTTPRequestException e ) { - this.failure( e.getMessage() ); + failure( e.getMessage() ); } catch( Exception e ) { - this.failure( "Could not connect" ); - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.error( "Error in websocket", e ); - } - } - } - - void failure( String message ) - { - if( this.tryClose() ) - { - this.environment.queueEvent( FAILURE_EVENT, this.address, message ); + failure( NetworkUtils.toFriendlyError( e ) ); + if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error in websocket", e ); } } void success( Channel channel, Options options ) { - if( this.isClosed() ) - { - return; - } + if( isClosed() ) return; WebsocketHandle handle = new WebsocketHandle( this, options, channel ); - this.environment().queueEvent( SUCCESS_EVENT, this.address, handle ); - this.websocketHandle = this.createOwnerReference( handle ); + environment().queueEvent( SUCCESS_EVENT, address, handle ); + websocketHandle = createOwnerReference( handle ); - this.checkClosed(); + checkClosed(); } - public IAPIEnvironment environment() + void failure( String message ) { - return this.environment; + if( tryClose() ) environment.queueEvent( FAILURE_EVENT, address, message ); } void close( int status, String reason ) { - if( this.tryClose() ) + if( tryClose() ) { - this.environment.queueEvent( CLOSE_EVENT, this.address, Strings.isNullOrEmpty( reason ) ? null : reason, status < 0 ? null : status ); + environment.queueEvent( CLOSE_EVENT, address, + Strings.isNullOrEmpty( reason ) ? null : reason, + status < 0 ? null : status ); } } @@ -242,17 +214,22 @@ public class Websocket extends Resource { super.dispose(); - this.executorFuture = closeFuture( this.executorFuture ); - this.connectFuture = closeChannel( this.connectFuture ); + executorFuture = closeFuture( executorFuture ); + connectFuture = closeChannel( connectFuture ); - WeakReference websocketHandleRef = this.websocketHandle; + WeakReference websocketHandleRef = websocketHandle; WebsocketHandle websocketHandle = websocketHandleRef == null ? null : websocketHandleRef.get(); IoUtil.closeQuietly( websocketHandle ); this.websocketHandle = null; } + public IAPIEnvironment environment() + { + return environment; + } + public String address() { - return this.address; + return address; } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java index 4931d2d63..0c74c0c9f 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java +++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http.websocket; import com.google.common.base.Objects; @@ -60,21 +59,14 @@ public class WebsocketHandle implements Closeable @LuaFunction public final MethodResult receive( Optional timeout ) throws LuaException { - this.checkOpen(); - int timeoutId = timeout.isPresent() ? this.websocket.environment() - .startTimer( Math.round( checkFinite( 0, timeout.get() ) / 0.05 ) ) : -1; + checkOpen(); + int timeoutId = timeout.isPresent() + ? websocket.environment().startTimer( Math.round( checkFinite( 0, timeout.get() ) / 0.05 ) ) + : -1; return new ReceiveCallback( timeoutId ).pull; } - private void checkOpen() throws LuaException - { - if( this.closed ) - { - throw new LuaException( "attempt to use a closed file" ); - } - } - /** * Send a websocket message to the connected server. * @@ -86,39 +78,45 @@ public class WebsocketHandle implements Closeable @LuaFunction public final void send( Object message, Optional binary ) throws LuaException { - this.checkOpen(); + checkOpen(); String text = StringUtil.toString( message ); - if( this.options.websocketMessage != 0 && text.length() > this.options.websocketMessage ) + if( options.websocketMessage != 0 && text.length() > options.websocketMessage ) { throw new LuaException( "Message is too large" ); } - this.websocket.environment() - .addTrackingChange( TrackingField.WEBSOCKET_OUTGOING, text.length() ); + websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_OUTGOING, text.length() ); Channel channel = this.channel; if( channel != null ) { - channel.writeAndFlush( binary.orElse( false ) ? new BinaryWebSocketFrame( Unpooled.wrappedBuffer( LuaValues.encode( text ) ) ) : new TextWebSocketFrame( - text ) ); + channel.writeAndFlush( binary.orElse( false ) + ? new BinaryWebSocketFrame( Unpooled.wrappedBuffer( LuaValues.encode( text ) ) ) + : new TextWebSocketFrame( text ) ); } } /** - * Close this websocket. This will terminate the connection, meaning messages can no longer be sent or received along it. + * Close this websocket. This will terminate the connection, meaning messages can no longer be sent or received + * along it. */ @LuaFunction( "close" ) public final void doClose() { - this.close(); - this.websocket.close(); + close(); + websocket.close(); + } + + private void checkOpen() throws LuaException + { + if( closed ) throw new LuaException( "attempt to use a closed file" ); } @Override public void close() { - this.closed = true; + closed = true; Channel channel = this.channel; if( channel != null ) @@ -142,23 +140,23 @@ public class WebsocketHandle implements Closeable @Override public MethodResult resume( Object[] event ) { - if( event.length >= 3 && Objects.equal( event[0], MESSAGE_EVENT ) && Objects.equal( event[1], WebsocketHandle.this.websocket.address() ) ) + if( event.length >= 3 && Objects.equal( event[0], MESSAGE_EVENT ) && Objects.equal( event[1], websocket.address() ) ) { return MethodResult.of( Arrays.copyOfRange( event, 2, event.length ) ); } - else if( event.length >= 2 && Objects.equal( event[0], CLOSE_EVENT ) && Objects.equal( event[1], WebsocketHandle.this.websocket.address() ) && WebsocketHandle.this.closed ) + else if( event.length >= 2 && Objects.equal( event[0], CLOSE_EVENT ) && Objects.equal( event[1], websocket.address() ) && closed ) { // If the socket is closed abort. return MethodResult.of(); } - else if( event.length >= 2 && this.timeoutId != -1 && Objects.equal( event[0], - TIMER_EVENT ) && event[1] instanceof Number && ((Number) event[1]).intValue() == this.timeoutId ) + else if( event.length >= 2 && timeoutId != -1 && Objects.equal( event[0], TIMER_EVENT ) + && event[1] instanceof Number && ((Number) event[1]).intValue() == timeoutId ) { // If we received a matching timer event then abort. return MethodResult.of(); } - return this.pull; + return pull; } } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java index 7aa2fdd30..4916f5fbd 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java +++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java @@ -3,20 +3,15 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.http.websocket; -import dan200.computercraft.core.apis.http.HTTPRequestException; import dan200.computercraft.core.apis.http.NetworkUtils; import dan200.computercraft.core.apis.http.options.Options; import dan200.computercraft.core.tracking.TrackingField; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ConnectTimeoutException; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.TooLongFrameException; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.websocketx.*; -import io.netty.handler.timeout.ReadTimeoutException; import io.netty.util.CharsetUtil; import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT; @@ -37,70 +32,33 @@ public class WebsocketHandler extends SimpleChannelInboundHandler @Override public void channelActive( ChannelHandlerContext ctx ) throws Exception { - this.handshaker.handshake( ctx.channel() ); + handshaker.handshake( ctx.channel() ); super.channelActive( ctx ); } @Override public void channelInactive( ChannelHandlerContext ctx ) throws Exception { - this.websocket.close( -1, "Websocket is inactive" ); + websocket.close( -1, "Websocket is inactive" ); super.channelInactive( ctx ); } - @Override - public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) - { - ctx.close(); - - String message; - if( cause instanceof WebSocketHandshakeException || cause instanceof HTTPRequestException ) - { - message = cause.getMessage(); - } - else if( cause instanceof TooLongFrameException ) - { - message = "Message is too large"; - } - else if( cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException ) - { - message = "Timed out"; - } - else - { - message = "Could not connect"; - } - - if( this.handshaker.isHandshakeComplete() ) - { - this.websocket.close( -1, message ); - } - else - { - this.websocket.failure( message ); - } - } - @Override public void channelRead0( ChannelHandlerContext ctx, Object msg ) { - if( this.websocket.isClosed() ) - { - return; - } + if( websocket.isClosed() ) return; - if( !this.handshaker.isHandshakeComplete() ) + if( !handshaker.isHandshakeComplete() ) { - this.handshaker.finishHandshake( ctx.channel(), (FullHttpResponse) msg ); - this.websocket.success( ctx.channel(), this.options ); + handshaker.finishHandshake( ctx.channel(), (FullHttpResponse) msg ); + websocket.success( ctx.channel(), options ); return; } if( msg instanceof FullHttpResponse ) { FullHttpResponse response = (FullHttpResponse) msg; - throw new IllegalStateException( "Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content() - .toString( CharsetUtil.UTF_8 ) + ')' ); + throw new IllegalStateException( "Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString( CharsetUtil.UTF_8 ) + ')' ); } WebSocketFrame frame = (WebSocketFrame) msg; @@ -108,31 +66,41 @@ public class WebsocketHandler extends SimpleChannelInboundHandler { String data = ((TextWebSocketFrame) frame).text(); - this.websocket.environment() - .addTrackingChange( TrackingField.WEBSOCKET_INCOMING, data.length() ); - this.websocket.environment() - .queueEvent( MESSAGE_EVENT, this.websocket.address(), data, false ); + websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_INCOMING, data.length() ); + websocket.environment().queueEvent( MESSAGE_EVENT, websocket.address(), data, false ); } else if( frame instanceof BinaryWebSocketFrame ) { byte[] converted = NetworkUtils.toBytes( frame.content() ); - this.websocket.environment() - .addTrackingChange( TrackingField.WEBSOCKET_INCOMING, converted.length ); - this.websocket.environment() - .queueEvent( MESSAGE_EVENT, this.websocket.address(), converted, true ); + websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_INCOMING, converted.length ); + websocket.environment().queueEvent( MESSAGE_EVENT, websocket.address(), converted, true ); } else if( frame instanceof CloseWebSocketFrame ) { CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame; - this.websocket.close( closeFrame.statusCode(), closeFrame.reasonText() ); + websocket.close( closeFrame.statusCode(), closeFrame.reasonText() ); } else if( frame instanceof PingWebSocketFrame ) { - frame.content() - .retain(); - ctx.channel() - .writeAndFlush( new PongWebSocketFrame( frame.content() ) ); + frame.content().retain(); + ctx.channel().writeAndFlush( new PongWebSocketFrame( frame.content() ) ); + } + } + + @Override + public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) + { + ctx.close(); + + String message = NetworkUtils.toFriendlyError( cause ); + if( handshaker.isHandshakeComplete() ) + { + websocket.close( -1, message ); + } + else + { + websocket.failure( message ); } } } diff --git a/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java b/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java index 404c02715..34e9be132 100644 --- a/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java +++ b/src/main/java/dan200/computercraft/core/asm/DeclaringClassLoader.java @@ -18,6 +18,6 @@ final class DeclaringClassLoader extends ClassLoader Class define( String name, byte[] bytes, ProtectionDomain protectionDomain ) throws ClassFormatError { - return this.defineClass( name, bytes, 0, bytes.length, protectionDomain ); + return defineClass( name, bytes, 0, bytes.length, protectionDomain ); } } diff --git a/src/main/java/dan200/computercraft/core/asm/Generator.java b/src/main/java/dan200/computercraft/core/asm/Generator.java index 4da5a1b70..c630b140f 100644 --- a/src/main/java/dan200/computercraft/core/asm/Generator.java +++ b/src/main/java/dan200/computercraft/core/asm/Generator.java @@ -11,10 +11,7 @@ import com.google.common.cache.LoadingCache; import com.google.common.primitives.Primitives; import com.google.common.reflect.TypeToken; import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.lua.*; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; @@ -53,11 +50,15 @@ public final class Generator private final String methodDesc; private final Function wrap; - private final LoadingCache> methodCache = CacheBuilder.newBuilder() - .build( CacheLoader.from( catching( this::build, Optional.empty() ) ) ); - private final LoadingCache, List>> classCache = CacheBuilder.newBuilder() + + private final LoadingCache, List>> classCache = CacheBuilder + .newBuilder() .build( CacheLoader.from( catching( this::build, Collections.emptyList() ) ) ); + private final LoadingCache> methodCache = CacheBuilder + .newBuilder() + .build( CacheLoader.from( catching( this::build, Optional.empty() ) ) ); + Generator( Class base, List> context, Function wrap ) { this.base = base; @@ -66,13 +67,8 @@ public final class Generator this.wrap = wrap; StringBuilder methodDesc = new StringBuilder().append( "(Ljava/lang/Object;" ); - for( Class klass : context ) - { - methodDesc.append( Type.getDescriptor( klass ) ); - } - methodDesc.append( DESC_ARGUMENTS ) - .append( ")" ) - .append( DESC_METHOD_RESULT ); + for( Class klass : context ) methodDesc.append( Type.getDescriptor( klass ) ); + methodDesc.append( DESC_ARGUMENTS ).append( ")" ).append( DESC_METHOD_RESULT ); this.methodDesc = methodDesc.toString(); } @@ -81,7 +77,7 @@ public final class Generator { try { - return this.classCache.get( klass ); + return classCache.get( klass ); } catch( ExecutionException e ) { @@ -97,10 +93,7 @@ public final class Generator for( Method method : klass.getMethods() ) { LuaFunction annotation = method.getAnnotation( LuaFunction.class ); - if( annotation == null ) - { - continue; - } + if( annotation == null ) continue; if( Modifier.isStatic( method.getModifiers() ) ) { @@ -108,52 +101,32 @@ public final class Generator continue; } - T instance = this.methodCache.getUnchecked( method ) - .orElse( null ); - if( instance == null ) - { - continue; - } + T instance = methodCache.getUnchecked( method ).orElse( null ); + if( instance == null ) continue; - if( methods == null ) - { - methods = new ArrayList<>(); - } - this.addMethod( methods, method, annotation, instance ); + if( methods == null ) methods = new ArrayList<>(); + addMethod( methods, method, annotation, instance ); } for( GenericMethod method : GenericMethod.all() ) { if( !method.target.isAssignableFrom( klass ) ) continue; - T instance = this.methodCache.getUnchecked( method.method ) - .orElse( null ); - if( instance == null ) - { - continue; - } + T instance = methodCache.getUnchecked( method.method ).orElse( null ); + if( instance == null ) continue; - if( methods == null ) - { - methods = new ArrayList<>(); - } - this.addMethod( methods, method.method, method.annotation, instance ); + if( methods == null ) methods = new ArrayList<>(); + addMethod( methods, method.method, method.annotation, instance ); } - if( methods == null ) - { - return Collections.emptyList(); - } + if( methods == null ) return Collections.emptyList(); methods.trimToSize(); return Collections.unmodifiableList( methods ); } private void addMethod( List> methods, Method method, LuaFunction annotation, T instance ) { - if( annotation.mainThread() ) - { - instance = this.wrap.apply( instance ); - } + if( annotation.mainThread() ) instance = wrap.apply( instance ); String[] names = annotation.value(); boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread(); @@ -173,8 +146,7 @@ public final class Generator @Nonnull private Optional build( Method method ) { - String name = method.getDeclaringClass() - .getName() + "." + method.getName(); + String name = method.getDeclaringClass().getName() + "." + method.getName(); int modifiers = method.getModifiers(); // Instance methods must be final - this prevents them being overridden and potentially exposed twice. @@ -189,8 +161,7 @@ public final class Generator return Optional.empty(); } - if( !Modifier.isPublic( method.getDeclaringClass() - .getModifiers() ) ) + if( !Modifier.isPublic( method.getDeclaringClass().getModifiers() ) ) { ComputerCraft.log.error( "Lua Method {} should be on a public class.", name ); return Optional.empty(); @@ -214,21 +185,12 @@ public final class Generator try { - String className = method.getDeclaringClass() - .getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement(); - byte[] bytes = this.generate( className, target, method ); - if( bytes == null ) - { - return Optional.empty(); - } + String className = method.getDeclaringClass().getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement(); + byte[] bytes = generate( className, target, method ); + if( bytes == null ) return Optional.empty(); - Class klass = DeclaringClassLoader.INSTANCE.define( className, - bytes, - method.getDeclaringClass() - .getProtectionDomain() ); - return Optional.of( klass.asSubclass( this.base ) - .getDeclaredConstructor() - .newInstance() ); + Class klass = DeclaringClassLoader.INSTANCE.define( className, bytes, method.getDeclaringClass().getProtectionDomain() ); + return Optional.of( klass.asSubclass( base ).getDeclaredConstructor().newInstance() ); } catch( ReflectiveOperationException | ClassFormatError | RuntimeException e ) { @@ -245,7 +207,7 @@ public final class Generator // Construct a public final class which extends Object and implements MethodInstance.Delegate ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS ); - cw.visit( V1_8, ACC_PUBLIC | ACC_FINAL, internalName, null, "java/lang/Object", this.interfaces ); + cw.visit( V1_8, ACC_PUBLIC | ACC_FINAL, internalName, null, "java/lang/Object", interfaces ); cw.visitSource( "CC generated method", null ); { // Constructor just invokes super. @@ -259,7 +221,7 @@ public final class Generator } { - MethodVisitor mw = cw.visitMethod( ACC_PUBLIC, METHOD_NAME, this.methodDesc, null, EXCEPTIONS ); + MethodVisitor mw = cw.visitMethod( ACC_PUBLIC, METHOD_NAME, methodDesc, null, EXCEPTIONS ); mw.visitCode(); // If we're an instance method, load the this parameter. @@ -272,22 +234,16 @@ public final class Generator int argIndex = 0; for( java.lang.reflect.Type genericArg : method.getGenericParameterTypes() ) { - Boolean loadedArg = this.loadArg( mw, target, method, genericArg, argIndex ); - if( loadedArg == null ) - { - return null; - } - if( loadedArg ) - { - argIndex++; - } + Boolean loadedArg = loadArg( mw, target, method, genericArg, argIndex ); + if( loadedArg == null ) return null; + if( loadedArg ) argIndex++; } - mw.visitMethodInsn( Modifier.isStatic( method.getModifiers() ) ? INVOKESTATIC : INVOKEVIRTUAL, - Type.getInternalName( method.getDeclaringClass() ), - method.getName(), - Type.getMethodDescriptor( method ), - false ); + mw.visitMethodInsn( + Modifier.isStatic( method.getModifiers() ) ? INVOKESTATIC : INVOKEVIRTUAL, + Type.getInternalName( method.getDeclaringClass() ), method.getName(), + Type.getMethodDescriptor( method ), false + ); // We allow a reasonable amount of flexibility on the return value's type. Alongside the obvious MethodResult, // we convert basic types into an immediate result. @@ -301,11 +257,7 @@ public final class Generator else if( ret.isPrimitive() ) { Class boxed = Primitives.wrap( ret ); - mw.visitMethodInsn( INVOKESTATIC, - Type.getInternalName( boxed ), - "valueOf", - "(" + Type.getDescriptor( ret ) + ")" + Type.getDescriptor( boxed ), - false ); + mw.visitMethodInsn( INVOKESTATIC, Type.getInternalName( boxed ), "valueOf", "(" + Type.getDescriptor( ret ) + ")" + Type.getDescriptor( boxed ), false ); mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "(Ljava/lang/Object;)" + DESC_METHOD_RESULT, false ); } else if( ret == Object[].class ) @@ -339,18 +291,15 @@ public final class Generator } Class arg = Reflect.getRawType( method, genericArg, true ); - if( arg == null ) - { - return null; - } + if( arg == null ) return null; if( arg == IArguments.class ) { - mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + mw.visitVarInsn( ALOAD, 2 + context.size() ); return false; } - int idx = this.context.indexOf( arg ); + int idx = context.indexOf( arg ); if( idx >= 0 ) { mw.visitVarInsn( ALOAD, 2 + idx ); @@ -359,19 +308,12 @@ public final class Generator if( arg == Optional.class ) { - Class klass = Reflect.getRawType( method, - TypeToken.of( genericArg ) - .resolveType( Reflect.OPTIONAL_IN ) - .getType(), - false ); - if( klass == null ) - { - return null; - } + Class klass = Reflect.getRawType( method, TypeToken.of( genericArg ).resolveType( Reflect.OPTIONAL_IN ).getType(), false ); + if( klass == null ) return null; if( Enum.class.isAssignableFrom( klass ) && klass != Enum.class ) { - mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + mw.visitVarInsn( ALOAD, 2 + context.size() ); Reflect.loadInt( mw, argIndex ); mw.visitLdcInsn( Type.getType( klass ) ); mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "optEnum", "(ILjava/lang/Class;)Ljava/util/Optional;", true ); @@ -381,7 +323,7 @@ public final class Generator String name = Reflect.getLuaName( Primitives.unwrap( klass ) ); if( name != null ) { - mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + mw.visitVarInsn( ALOAD, 2 + context.size() ); Reflect.loadInt( mw, argIndex ); mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "opt" + name, "(I)Ljava/util/Optional;", true ); return true; @@ -390,7 +332,7 @@ public final class Generator if( Enum.class.isAssignableFrom( arg ) && arg != Enum.class ) { - mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + mw.visitVarInsn( ALOAD, 2 + context.size() ); Reflect.loadInt( mw, argIndex ); mw.visitLdcInsn( Type.getType( arg ) ); mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "getEnum", "(ILjava/lang/Class;)Ljava/lang/Enum;", true ); @@ -401,22 +343,16 @@ public final class Generator String name = arg == Object.class ? "" : Reflect.getLuaName( arg ); if( name != null ) { - if( Reflect.getRawType( method, genericArg, false ) == null ) - { - return null; - } + if( Reflect.getRawType( method, genericArg, false ) == null ) return null; - mw.visitVarInsn( ALOAD, 2 + this.context.size() ); + mw.visitVarInsn( ALOAD, 2 + context.size() ); Reflect.loadInt( mw, argIndex ); mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "get" + name, "(I)" + Type.getDescriptor( arg ), true ); return true; } ComputerCraft.log.error( "Unknown parameter type {} for method {}.{}.", - arg.getName(), - method.getDeclaringClass() - .getName(), - method.getName() ); + arg.getName(), method.getDeclaringClass().getName(), method.getName() ); return null; } diff --git a/src/main/java/dan200/computercraft/core/asm/IntCache.java b/src/main/java/dan200/computercraft/core/asm/IntCache.java index cb1056dee..ec634b3cb 100644 --- a/src/main/java/dan200/computercraft/core/asm/IntCache.java +++ b/src/main/java/dan200/computercraft/core/asm/IntCache.java @@ -21,31 +21,19 @@ public final class IntCache @SuppressWarnings( "unchecked" ) public T get( int index ) { - if( index < 0 ) - { - throw new IllegalArgumentException( "index < 0" ); - } + if( index < 0 ) throw new IllegalArgumentException( "index < 0" ); - if( index < this.cache.length ) + if( index < cache.length ) { - T current = (T) this.cache[index]; - if( current != null ) - { - return current; - } + T current = (T) cache[index]; + if( current != null ) return current; } synchronized( this ) { - if( index >= this.cache.length ) - { - this.cache = Arrays.copyOf( this.cache, Math.max( this.cache.length * 2, index + 1 ) ); - } - T current = (T) this.cache[index]; - if( current == null ) - { - this.cache[index] = current = this.factory.apply( index ); - } + if( index >= cache.length ) cache = Arrays.copyOf( cache, Math.max( cache.length * 2, index + 1 ) ); + T current = (T) cache[index]; + if( current == null ) cache[index] = current = factory.apply( index ); return current; } } diff --git a/src/main/java/dan200/computercraft/core/asm/LuaMethod.java b/src/main/java/dan200/computercraft/core/asm/LuaMethod.java index 87c454878..b0562835c 100644 --- a/src/main/java/dan200/computercraft/core/asm/LuaMethod.java +++ b/src/main/java/dan200/computercraft/core/asm/LuaMethod.java @@ -12,14 +12,13 @@ import java.util.Collections; public interface LuaMethod { - Generator GENERATOR = new Generator<>( LuaMethod.class, - Collections.singletonList( ILuaContext.class ), - m -> ( target, context, args ) -> TaskCallback.make( context, - () -> TaskCallback.checkUnwrap( m.apply( target, - context, - args ) ) ) ); + Generator GENERATOR = new Generator<>( LuaMethod.class, Collections.singletonList( ILuaContext.class ), + m -> ( target, context, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, args ) ) ) + ); - IntCache DYNAMIC = new IntCache<>( method -> ( instance, context, args ) -> ((IDynamicLuaObject) instance).callMethod( context, method, args ) ); + IntCache DYNAMIC = new IntCache<>( + method -> ( instance, context, args ) -> ((IDynamicLuaObject) instance).callMethod( context, method, args ) + ); String[] EMPTY_METHODS = new String[0]; diff --git a/src/main/java/dan200/computercraft/core/asm/NamedMethod.java b/src/main/java/dan200/computercraft/core/asm/NamedMethod.java index ffb6e0b8b..ea72bb7a4 100644 --- a/src/main/java/dan200/computercraft/core/asm/NamedMethod.java +++ b/src/main/java/dan200/computercraft/core/asm/NamedMethod.java @@ -23,17 +23,17 @@ public final class NamedMethod @Nonnull public String getName() { - return this.name; + return name; } @Nonnull public T getMethod() { - return this.method; + return method; } public boolean nonYielding() { - return this.nonYielding; + return nonYielding; } } diff --git a/src/main/java/dan200/computercraft/core/asm/ObjectSource.java b/src/main/java/dan200/computercraft/core/asm/ObjectSource.java index 9ea11f60d..06ecbaf03 100644 --- a/src/main/java/dan200/computercraft/core/asm/ObjectSource.java +++ b/src/main/java/dan200/computercraft/core/asm/ObjectSource.java @@ -10,29 +10,23 @@ import java.util.function.BiConsumer; /** * A Lua object which exposes additional methods. * - * This can be used to merge multiple objects together into one. Ideally this'd be part of the API, but I'm not entirely happy with the interface - - * something I'd like to think about first. + * This can be used to merge multiple objects together into one. Ideally this'd be part of the API, but I'm not entirely + * happy with the interface - something I'd like to think about first. */ public interface ObjectSource { + Iterable getExtra(); + static void allMethods( Generator generator, Object object, BiConsumer> accept ) { - for( NamedMethod method : generator.getMethods( object.getClass() ) ) - { - accept.accept( object, method ); - } + for( NamedMethod method : generator.getMethods( object.getClass() ) ) accept.accept( object, method ); if( object instanceof ObjectSource ) { for( Object extra : ((ObjectSource) object).getExtra() ) { - for( NamedMethod method : generator.getMethods( extra.getClass() ) ) - { - accept.accept( extra, method ); - } + for( NamedMethod method : generator.getMethods( extra.getClass() ) ) accept.accept( extra, method ); } } } - - Iterable getExtra(); } diff --git a/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java b/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java index 959fbb5d5..38618442f 100644 --- a/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java +++ b/src/main/java/dan200/computercraft/core/asm/PeripheralMethod.java @@ -17,19 +17,13 @@ import java.util.Arrays; public interface PeripheralMethod { - Generator GENERATOR = new Generator<>( PeripheralMethod.class, - Arrays.asList( ILuaContext.class, IComputerAccess.class ), - m -> ( target, context, computer, args ) -> TaskCallback.make( context, - () -> TaskCallback.checkUnwrap( m.apply( - target, - context, - computer, - args ) ) ) ); + Generator GENERATOR = new Generator<>( PeripheralMethod.class, Arrays.asList( ILuaContext.class, IComputerAccess.class ), + m -> ( target, context, computer, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, computer, args ) ) ) + ); - IntCache DYNAMIC = new IntCache<>( method -> ( instance, context, computer, args ) -> ((IDynamicPeripheral) instance).callMethod( computer, - context, - method, - args ) ); + IntCache DYNAMIC = new IntCache<>( + method -> ( instance, context, computer, args ) -> ((IDynamicPeripheral) instance).callMethod( computer, context, method, args ) + ); @Nonnull MethodResult apply( @Nonnull Object target, @Nonnull ILuaContext context, @Nonnull IComputerAccess computer, @Nonnull IArguments args ) throws LuaException; diff --git a/src/main/java/dan200/computercraft/core/asm/Reflect.java b/src/main/java/dan200/computercraft/core/asm/Reflect.java index 15e016215..4517fecc3 100644 --- a/src/main/java/dan200/computercraft/core/asm/Reflect.java +++ b/src/main/java/dan200/computercraft/core/asm/Reflect.java @@ -29,37 +29,16 @@ final class Reflect { if( klass.isPrimitive() ) { - if( klass == int.class ) - { - return "Int"; - } - if( klass == boolean.class ) - { - return "Boolean"; - } - if( klass == double.class ) - { - return "Double"; - } - if( klass == long.class ) - { - return "Long"; - } + if( klass == int.class ) return "Int"; + if( klass == boolean.class ) return "Boolean"; + if( klass == double.class ) return "Double"; + if( klass == long.class ) return "Long"; } else { - if( klass == Map.class ) - { - return "Table"; - } - if( klass == String.class ) - { - return "String"; - } - if( klass == ByteBuffer.class ) - { - return "Bytes"; - } + if( klass == Map.class ) return "Table"; + if( klass == String.class ) return "String"; + if( klass == ByteBuffer.class ) return "Bytes"; } return null; @@ -71,10 +50,7 @@ final class Reflect Type underlying = root; while( true ) { - if( underlying instanceof Class ) - { - return (Class) underlying; - } + if( underlying instanceof Class ) return (Class) underlying; if( underlying instanceof ParameterizedType ) { @@ -83,21 +59,13 @@ final class Reflect { for( java.lang.reflect.Type arg : type.getActualTypeArguments() ) { - if( arg instanceof WildcardType ) - { - continue; - } - if( arg instanceof TypeVariable && ((TypeVariable) arg).getName() - .startsWith( "capture#" ) ) + if( arg instanceof WildcardType ) continue; + if( arg instanceof TypeVariable && ((TypeVariable) arg).getName().startsWith( "capture#" ) ) { continue; } - ComputerCraft.log.error( "Method {}.{} has generic type {} with non-wildcard argument {}.", - method.getDeclaringClass(), - method.getName(), - root, - arg ); + ComputerCraft.log.error( "Method {}.{} has generic type {} with non-wildcard argument {}.", method.getDeclaringClass(), method.getName(), root, arg ); return null; } } diff --git a/src/main/java/dan200/computercraft/core/asm/TaskCallback.java b/src/main/java/dan200/computercraft/core/asm/TaskCallback.java index b5c208a29..1298391e4 100644 --- a/src/main/java/dan200/computercraft/core/asm/TaskCallback.java +++ b/src/main/java/dan200/computercraft/core/asm/TaskCallback.java @@ -20,6 +20,33 @@ public final class TaskCallback implements ILuaCallback this.task = task; } + @Nonnull + @Override + public MethodResult resume( Object[] response ) throws LuaException + { + if( response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean) ) + { + return pull; + } + + if( ((Number) response[1]).longValue() != task ) return pull; + + if( (Boolean) response[2] ) + { + // Extract the return values from the event and return them + return MethodResult.of( Arrays.copyOfRange( response, 3, response.length ) ); + } + else if( response.length >= 4 && response[3] instanceof String ) + { + // Extract the error message from the event and raise it + throw new LuaException( (String) response[3] ); + } + else + { + throw new LuaException( "error" ); + } + } + static Object[] checkUnwrap( MethodResult result ) { if( result.getCallback() != null ) @@ -37,34 +64,4 @@ public final class TaskCallback implements ILuaCallback long task = context.issueMainThreadTask( func ); return new TaskCallback( task ).pull; } - - @Nonnull - @Override - public MethodResult resume( Object[] response ) throws LuaException - { - if( response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean) ) - { - return this.pull; - } - - if( ((Number) response[1]).longValue() != this.task ) - { - return this.pull; - } - - if( (Boolean) response[2] ) - { - // Extract the return values from the event and return them - return MethodResult.of( Arrays.copyOfRange( response, 3, response.length ) ); - } - else if( response.length >= 4 && response[3] instanceof String ) - { - // Extract the error message from the event and raise it - throw new LuaException( (String) response[3] ); - } - else - { - throw new LuaException( "error" ); - } - } } diff --git a/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java b/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java index bea5b44c8..6265b127d 100644 --- a/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java +++ b/src/main/java/dan200/computercraft/core/computer/ApiWrapper.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.api.lua.ILuaAPI; @@ -25,30 +24,30 @@ final class ApiWrapper implements ILuaAPI @Override public String[] getNames() { - return this.delegate.getNames(); + return delegate.getNames(); } @Override public void startup() { - this.delegate.startup(); + delegate.startup(); } @Override public void update() { - this.delegate.update(); + delegate.update(); } @Override public void shutdown() { - this.delegate.shutdown(); - this.system.unmountAll(); + delegate.shutdown(); + system.unmountAll(); } public ILuaAPI getDelegate() { - return this.delegate; + return delegate; } } diff --git a/src/main/java/dan200/computercraft/core/computer/Computer.java b/src/main/java/dan200/computercraft/core/computer/Computer.java index db70b2e88..005625230 100644 --- a/src/main/java/dan200/computercraft/core/computer/Computer.java +++ b/src/main/java/dan200/computercraft/core/computer/Computer.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import com.google.common.base.Objects; @@ -31,79 +30,88 @@ import java.util.concurrent.atomic.AtomicBoolean; public class Computer { private static final int START_DELAY = 50; + + // Various properties of the computer + private int id; + private String label = null; + // Read-only fields about the computer - private final IComputerEnvironment m_environment; - private final Terminal m_terminal; + private final IComputerEnvironment environment; + private final Terminal terminal; private final ComputerExecutor executor; private final MainThreadExecutor serverExecutor; + + // Additional state about the computer and its environment. + private boolean blinking = false; private final Environment internalEnvironment = new Environment( this ); private final AtomicBoolean externalOutputChanged = new AtomicBoolean(); - // Various properties of the computer - private int m_id; - private String m_label = null; - // Additional state about the computer and its environment. - private boolean m_blinking = false; + private boolean startRequested; - private int m_ticksSinceStart = -1; + private int ticksSinceStart = -1; public Computer( IComputerEnvironment environment, Terminal terminal, int id ) { - this.m_id = id; - this.m_environment = environment; - this.m_terminal = terminal; + this.id = id; + this.environment = environment; + this.terminal = terminal; - this.executor = new ComputerExecutor( this ); - this.serverExecutor = new MainThreadExecutor( this ); + executor = new ComputerExecutor( this ); + serverExecutor = new MainThreadExecutor( this ); } IComputerEnvironment getComputerEnvironment() { - return this.m_environment; + return environment; } FileSystem getFileSystem() { - return this.executor.getFileSystem(); + return executor.getFileSystem(); } Terminal getTerminal() { - return this.m_terminal; + return terminal; } public Environment getEnvironment() { - return this.internalEnvironment; + return internalEnvironment; } public IAPIEnvironment getAPIEnvironment() { - return this.internalEnvironment; + return internalEnvironment; + } + + public boolean isOn() + { + return executor.isOn(); } public void turnOn() { - this.startRequested = true; + startRequested = true; } public void shutdown() { - this.executor.queueStop( false, false ); + executor.queueStop( false, false ); } public void reboot() { - this.executor.queueStop( true, false ); + executor.queueStop( true, false ); } public void unload() { - this.executor.queueStop( false, true ); + executor.queueStop( false, true ); } public void queueEvent( String event, Object[] args ) { - this.executor.queueEvent( event, args ); + executor.queueEvent( event, args ); } /** @@ -114,107 +122,98 @@ public class Computer */ public boolean queueMainThread( Runnable runnable ) { - return this.serverExecutor.enqueue( runnable ); + return serverExecutor.enqueue( runnable ); } public IWorkMonitor getMainThreadMonitor() { - return this.serverExecutor; + return serverExecutor; } public int getID() { - return this.m_id; - } - - public void setID( int id ) - { - this.m_id = id; + return id; } public int assignID() { - if( this.m_id < 0 ) + if( id < 0 ) { - this.m_id = this.m_environment.assignNewID(); + id = environment.assignNewID(); } - return this.m_id; + return id; + } + + public void setID( int id ) + { + this.id = id; } public String getLabel() { - return this.m_label; + return label; } public void setLabel( String label ) { - if( !Objects.equal( label, this.m_label ) ) + if( !Objects.equal( label, this.label ) ) { - this.m_label = label; - this.externalOutputChanged.set( true ); + this.label = label; + externalOutputChanged.set( true ); } } public void tick() { // We keep track of the number of ticks since the last start, only - if( this.m_ticksSinceStart >= 0 && this.m_ticksSinceStart <= START_DELAY ) - { - this.m_ticksSinceStart++; - } + if( ticksSinceStart >= 0 && ticksSinceStart <= START_DELAY ) ticksSinceStart++; - if( this.startRequested && (this.m_ticksSinceStart < 0 || this.m_ticksSinceStart > START_DELAY) ) + if( startRequested && (ticksSinceStart < 0 || ticksSinceStart > START_DELAY) ) { - this.startRequested = false; - if( !this.executor.isOn() ) + startRequested = false; + if( !executor.isOn() ) { - this.m_ticksSinceStart = 0; - this.executor.queueStart(); + ticksSinceStart = 0; + executor.queueStart(); } } - this.executor.tick(); + executor.tick(); // Update the environment's internal state. - this.internalEnvironment.tick(); + internalEnvironment.tick(); // Propagate the environment's output to the world. - if( this.internalEnvironment.updateOutput() ) - { - this.externalOutputChanged.set( true ); - } + if( internalEnvironment.updateOutput() ) externalOutputChanged.set( true ); // Set output changed if the terminal has changed from blinking to not - boolean blinking = this.m_terminal.getCursorBlink() && this.m_terminal.getCursorX() >= 0 && this.m_terminal.getCursorX() < this.m_terminal.getWidth() && this.m_terminal.getCursorY() >= 0 && this.m_terminal.getCursorY() < this.m_terminal.getHeight(); - if( blinking != this.m_blinking ) + boolean blinking = terminal.getCursorBlink() && + terminal.getCursorX() >= 0 && terminal.getCursorX() < terminal.getWidth() && + terminal.getCursorY() >= 0 && terminal.getCursorY() < terminal.getHeight(); + if( blinking != this.blinking ) { - this.m_blinking = blinking; - this.externalOutputChanged.set( true ); + this.blinking = blinking; + externalOutputChanged.set( true ); } } void markChanged() { - this.externalOutputChanged.set( true ); + externalOutputChanged.set( true ); } public boolean pollAndResetChanged() { - return this.externalOutputChanged.getAndSet( false ); + return externalOutputChanged.getAndSet( false ); } public boolean isBlinking() { - return this.isOn() && this.m_blinking; - } - - public boolean isOn() - { - return this.executor.isOn(); + return isOn() && blinking; } public void addApi( ILuaAPI api ) { - this.executor.addApi( api ); + executor.addApi( api ); } } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java index bb3b6681e..7ee1b742a 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.ComputerCraft; @@ -33,38 +32,50 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; /** - * The main task queue and executor for a single computer. This handles turning on and off a computer, as well as running events. + * The main task queue and executor for a single computer. This handles turning on and off a computer, as well as + * running events. * - * When the computer is instructed to turn on or off, or handle an event, we queue a task and register this to be executed on the {@link ComputerThread}. - * Note, as we may be starting many events in a single tick, the external cannot lock on anything which may be held for a long time. + * When the computer is instructed to turn on or off, or handle an event, we queue a task and register this to be + * executed on the {@link ComputerThread}. Note, as we may be starting many events in a single tick, the external + * cannot lock on anything which may be held for a long time. * - * The executor is effectively composed of two separate queues. Firstly, we have a "single element" queue {@link #command} which determines which state the - * computer should transition too. This is set by {@link #queueStart()} and {@link #queueStop(boolean, boolean)}. + * The executor is effectively composed of two separate queues. Firstly, we have a "single element" queue + * {@link #command} which determines which state the computer should transition too. This is set by + * {@link #queueStart()} and {@link #queueStop(boolean, boolean)}. * * When a computer is on, we simply push any events onto to the {@link #eventQueue}. * - * Both queues are run from the {@link #work()} method, which tries to execute a command if one exists, or resumes the machine with an event otherwise. + * Both queues are run from the {@link #work()} method, which tries to execute a command if one exists, or resumes the + * machine with an event otherwise. * - * One final responsibility for the executor is calling {@link ILuaAPI#update()} every tick, via the {@link #tick()} method. This should only be called when - * the computer is actually on ({@link #isOn}). + * One final responsibility for the executor is calling {@link ILuaAPI#update()} every tick, via the {@link #tick()} + * method. This should only be called when the computer is actually on ({@link #isOn}). */ final class ComputerExecutor { private static final int QUEUE_LIMIT = 256; - final TimeoutState timeout = new TimeoutState(); - /** - * The thread the executor is running on. This is non-null when performing work. We use this to ensure we're only doing one bit of work at one time. - * - * @see ComputerThread - */ - final AtomicReference executingThread = new AtomicReference<>(); + private final Computer computer; private final List apis = new ArrayList<>(); + final TimeoutState timeout = new TimeoutState(); + + private FileSystem fileSystem; + + private ILuaMachine machine; + + /** + * Whether the computer is currently on. This is set to false when a shutdown starts, or when turning on completes + * (but just before the Lua machine is started). + * + * @see #isOnLock + */ + private volatile boolean isOn = false; + /** * The lock to acquire when you need to modify the "on state" of a computer. * - * We hold this lock when running any command, and attempt to hold it when updating APIs. This ensures you don't update APIs while also - * starting/stopping them. + * We hold this lock when running any command, and attempt to hold it when updating APIs. This ensures you don't + * update APIs while also starting/stopping them. * * @see #isOn * @see #tick() @@ -72,17 +83,13 @@ final class ComputerExecutor * @see #shutdown() */ private final ReentrantLock isOnLock = new ReentrantLock(); + /** - * A lock used for any changes to {@link #eventQueue}, {@link #command} or {@link #onComputerQueue}. This will be used on the main thread, so locks - * should be kept as brief as possible. + * A lock used for any changes to {@link #eventQueue}, {@link #command} or {@link #onComputerQueue}. This will be + * used on the main thread, so locks should be kept as brief as possible. */ private final Object queueLock = new Object(); - /** - * The queue of events which should be executed when this computer is on. - * - * Note, this should be empty if this computer is off - it is cleared on shutdown and when turning on again. - */ - private final Queue eventQueue = new ArrayDeque<>( 4 ); + /** * Determines if this executor is present within {@link ComputerThread}. * @@ -91,37 +98,39 @@ final class ComputerExecutor * @see #afterWork() */ volatile boolean onComputerQueue = false; + /** * The amount of time this computer has used on a theoretical machine which shares work evenly amongst computers. * * @see ComputerThread */ long virtualRuntime = 0; + /** * The last time at which we updated {@link #virtualRuntime}. * * @see ComputerThread */ long vRuntimeStart; - private FileSystem fileSystem; - private ILuaMachine machine; - /** - * Whether the computer is currently on. This is set to false when a shutdown starts, or when turning on completes (but just before the Lua machine is - * started). - * - * @see #isOnLock - */ - private volatile boolean isOn = false; + /** * The command that {@link #work()} should execute on the computer thread. * - * One sets the command with {@link #queueStart()} and {@link #queueStop(boolean, boolean)}. Neither of these will queue a new event if there is an - * existing one in the queue. + * One sets the command with {@link #queueStart()} and {@link #queueStop(boolean, boolean)}. Neither of these will + * queue a new event if there is an existing one in the queue. * - * Note, if command is not {@code null}, then some command is scheduled to be executed. Otherwise it is not currently in the queue (or is currently - * being executed). + * Note, if command is not {@code null}, then some command is scheduled to be executed. Otherwise it is not + * currently in the queue (or is currently being executed). */ private volatile StateCommand command; + + /** + * The queue of events which should be executed when this computer is on. + * + * Note, this should be empty if this computer is off - it is cleared on shutdown and when turning on again. + */ + private final Queue eventQueue = new ArrayDeque<>( 4 ); + /** * Whether we interrupted an event and so should resume it instead of executing another task. * @@ -129,14 +138,24 @@ final class ComputerExecutor * @see #resumeMachine(String, Object[]) */ private boolean interruptedEvent = false; + /** * Whether this executor has been closed, and will no longer accept any incoming commands or events. * * @see #queueStop(boolean, boolean) */ private boolean closed; + private IWritableMount rootMount; + /** + * The thread the executor is running on. This is non-null when performing work. We use this to ensure we're only + * doing one bit of work at one time. + * + * @see ComputerThread + */ + final AtomicReference executingThread = new AtomicReference<>(); + ComputerExecutor( Computer computer ) { // Ensure the computer thread is running as required. @@ -147,41 +166,40 @@ final class ComputerExecutor Environment environment = computer.getEnvironment(); // Add all default APIs to the loaded list. - this.apis.add( new TermAPI( environment ) ); - this.apis.add( new RedstoneAPI( environment ) ); - this.apis.add( new FSAPI( environment ) ); - this.apis.add( new PeripheralAPI( environment ) ); - this.apis.add( new OSAPI( environment ) ); - if( ComputerCraft.httpEnabled ) - { - this.apis.add( new HTTPAPI( environment ) ); - } + apis.add( new TermAPI( environment ) ); + apis.add( new RedstoneAPI( environment ) ); + apis.add( new FSAPI( environment ) ); + apis.add( new PeripheralAPI( environment ) ); + apis.add( new OSAPI( environment ) ); + if( ComputerCraft.httpEnabled ) apis.add( new HTTPAPI( environment ) ); // Load in the externally registered APIs. for( ILuaAPIFactory factory : ApiFactories.getAll() ) { ComputerSystem system = new ComputerSystem( environment ); ILuaAPI api = factory.create( system ); - if( api != null ) - { - this.apis.add( new ApiWrapper( api, system ) ); - } + if( api != null ) apis.add( new ApiWrapper( api, system ) ); } } boolean isOn() { - return this.isOn; + return isOn; } FileSystem getFileSystem() { - return this.fileSystem; + return fileSystem; + } + + Computer getComputer() + { + return computer; } void addApi( ILuaAPI api ) { - this.apis.add( api ); + apis.add( api ); } /** @@ -189,30 +207,13 @@ final class ComputerExecutor */ void queueStart() { - synchronized( this.queueLock ) + synchronized( queueLock ) { // We should only schedule a start if we're not currently on and there's turn on. - if( this.closed || this.isOn || this.command != null ) - { - return; - } + if( closed || isOn || command != null ) return; - this.command = StateCommand.TURN_ON; - this.enqueue(); - } - } - - /** - * Add this executor to the {@link ComputerThread} if not already there. - */ - private void enqueue() - { - synchronized( this.queueLock ) - { - if( !this.onComputerQueue ) - { - ComputerThread.queue( this ); - } + command = StateCommand.TURN_ON; + enqueue(); } } @@ -225,54 +226,54 @@ final class ComputerExecutor */ void queueStop( boolean reboot, boolean close ) { - synchronized( this.queueLock ) + synchronized( queueLock ) { - if( this.closed ) - { - return; - } - this.closed = close; + if( closed ) return; + closed = close; StateCommand newCommand = reboot ? StateCommand.REBOOT : StateCommand.SHUTDOWN; // We should only schedule a stop if we're currently on and there's no shutdown pending. - if( !this.isOn || this.command != null ) + if( !isOn || command != null ) { // If we're closing, set the command just in case. - if( close ) - { - this.command = newCommand; - } + if( close ) command = newCommand; return; } - this.command = newCommand; - this.enqueue(); + command = newCommand; + enqueue(); } } /** - * Abort this whole computer due to a timeout. This will immediately destroy the Lua machine, and then schedule a shutdown. + * Abort this whole computer due to a timeout. This will immediately destroy the Lua machine, + * and then schedule a shutdown. */ void abort() { - ILuaMachine machine = this.machine; - if( machine != null ) - { - machine.close(); - } + immediateFail( StateCommand.ABORT ); + } - synchronized( this.queueLock ) + /** + * Abort this whole computer due to an internal error. This will immediately destroy the Lua machine, + * and then schedule a shutdown. + */ + void fastFail() + { + immediateFail( StateCommand.ERROR ); + } + + private void immediateFail( StateCommand command ) + { + ILuaMachine machine = this.machine; + if( machine != null ) machine.close(); + + synchronized( queueLock ) { - if( this.closed ) - { - return; - } - this.command = StateCommand.ABORT; - if( this.isOn ) - { - this.enqueue(); - } + if( closed ) return; + this.command = command; + if( isOn ) enqueue(); } } @@ -285,23 +286,28 @@ final class ComputerExecutor void queueEvent( @Nonnull String event, @Nullable Object[] args ) { // Events should be skipped if we're not on. - if( !this.isOn ) - { - return; - } + if( !isOn ) return; - synchronized( this.queueLock ) + synchronized( queueLock ) { // And if we've got some command in the pipeline, then don't queue events - they'll // probably be disposed of anyway. // We also limit the number of events which can be queued. - if( this.closed || this.command != null || this.eventQueue.size() >= QUEUE_LIMIT ) - { - return; - } + if( closed || command != null || eventQueue.size() >= QUEUE_LIMIT ) return; - this.eventQueue.offer( new Event( event, args ) ); - this.enqueue(); + eventQueue.offer( new Event( event, args ) ); + enqueue(); + } + } + + /** + * Add this executor to the {@link ComputerThread} if not already there. + */ + private void enqueue() + { + synchronized( queueLock ) + { + if( !onComputerQueue ) ComputerThread.queue( this ); } } @@ -310,7 +316,7 @@ final class ComputerExecutor */ void tick() { - if( this.isOn && this.isOnLock.tryLock() ) + if( isOn && isOnLock.tryLock() ) { // This horrific structure means we don't try to update APIs while the state is being changed // (and so they may be running startup/shutdown). @@ -318,29 +324,191 @@ final class ComputerExecutor // beginning or end of a computer's lifetime. try { - if( this.isOn ) + if( isOn ) { // Advance our APIs. - for( ILuaAPI api : this.apis ) - { - api.update(); - } + for( ILuaAPI api : apis ) api.update(); } } finally { - this.isOnLock.unlock(); + isOnLock.unlock(); } } } + private IMount getRomMount() + { + return computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" ); + } + + private IWritableMount getRootMount() + { + if( rootMount == null ) + { + rootMount = computer.getComputerEnvironment().createSaveDirMount( + "computer/" + computer.assignID(), + computer.getComputerEnvironment().getComputerSpaceLimit() + ); + } + return rootMount; + } + + private FileSystem createFileSystem() + { + FileSystem filesystem = null; + try + { + filesystem = new FileSystem( "hdd", getRootMount() ); + + IMount romMount = getRomMount(); + if( romMount == null ) + { + displayFailure( "Cannot mount ROM", null ); + return null; + } + + filesystem.mount( "rom", "rom", romMount ); + return filesystem; + } + catch( FileSystemException e ) + { + if( filesystem != null ) filesystem.close(); + ComputerCraft.log.error( "Cannot mount computer filesystem", e ); + + displayFailure( "Cannot mount computer system", null ); + return null; + } + } + + private ILuaMachine createLuaMachine() + { + // Load the bios resource + InputStream biosStream = null; + try + { + biosStream = computer.getComputerEnvironment().createResourceFile( "computercraft", "lua/bios.lua" ); + } + catch( Exception ignored ) + { + } + + if( biosStream == null ) + { + displayFailure( "Error loading bios.lua", null ); + return null; + } + + // Create the lua machine + ILuaMachine machine = new CobaltLuaMachine( computer, timeout ); + + // Add the APIs. We unwrap them (yes, this is horrible) to get access to the underlying object. + for( ILuaAPI api : apis ) machine.addAPI( api instanceof ApiWrapper ? ((ApiWrapper) api).getDelegate() : api ); + + // Start the machine running the bios resource + MachineResult result = machine.loadBios( biosStream ); + IoUtil.closeQuietly( biosStream ); + + if( result.isError() ) + { + machine.close(); + displayFailure( "Error loading bios.lua", result.getMessage() ); + return null; + } + + return machine; + } + + private void turnOn() throws InterruptedException + { + isOnLock.lockInterruptibly(); + try + { + // Reset the terminal and event queue + computer.getTerminal().reset(); + interruptedEvent = false; + synchronized( queueLock ) + { + eventQueue.clear(); + } + + // Init filesystem + if( (fileSystem = createFileSystem()) == null ) + { + shutdown(); + return; + } + + // Init APIs + computer.getEnvironment().reset(); + for( ILuaAPI api : apis ) api.startup(); + + // Init lua + if( (machine = createLuaMachine()) == null ) + { + shutdown(); + return; + } + + // Initialisation has finished, so let's mark ourselves as on. + isOn = true; + computer.markChanged(); + } + finally + { + isOnLock.unlock(); + } + + // Now actually start the computer, now that everything is set up. + resumeMachine( null, null ); + } + + private void shutdown() throws InterruptedException + { + isOnLock.lockInterruptibly(); + try + { + isOn = false; + interruptedEvent = false; + synchronized( queueLock ) + { + eventQueue.clear(); + } + + // Shutdown Lua machine + if( machine != null ) + { + machine.close(); + machine = null; + } + + // Shutdown our APIs + for( ILuaAPI api : apis ) api.shutdown(); + computer.getEnvironment().reset(); + + // Unload filesystem + if( fileSystem != null ) + { + fileSystem.close(); + fileSystem = null; + } + + computer.getEnvironment().resetOutput(); + computer.markChanged(); + } + finally + { + isOnLock.unlock(); + } + } + /** * Called before calling {@link #work()}, setting up any important state. */ void beforeWork() { - this.vRuntimeStart = System.nanoTime(); - this.timeout.startTimer(); + vRuntimeStart = System.nanoTime(); + timeout.startTimer(); } /** @@ -350,35 +518,24 @@ final class ComputerExecutor */ boolean afterWork() { - if( this.interruptedEvent ) + if( interruptedEvent ) { - this.timeout.pauseTimer(); + timeout.pauseTimer(); } else { - this.timeout.stopTimer(); + timeout.stopTimer(); } - Tracking.addTaskTiming( this.getComputer(), this.timeout.nanoCurrent() ); + Tracking.addTaskTiming( getComputer(), timeout.nanoCurrent() ); - if( this.interruptedEvent ) + if( interruptedEvent ) return true; + + synchronized( queueLock ) { + if( eventQueue.isEmpty() && command == null ) return onComputerQueue = false; return true; } - - synchronized( this.queueLock ) - { - if( this.eventQueue.isEmpty() && this.command == null ) - { - return this.onComputerQueue = false; - } - return true; - } - } - - Computer getComputer() - { - return this.computer; } /** @@ -392,19 +549,19 @@ final class ComputerExecutor */ void work() throws InterruptedException { - if( this.interruptedEvent ) + if( interruptedEvent ) { - this.interruptedEvent = false; - if( this.machine != null ) + interruptedEvent = false; + if( machine != null ) { - this.resumeMachine( null, null ); + resumeMachine( null, null ); return; } } StateCommand command; Event event = null; - synchronized( this.queueLock ) + synchronized( queueLock ) { command = this.command; this.command = null; @@ -412,15 +569,15 @@ final class ComputerExecutor // If we've no command, pull something from the event queue instead. if( command == null ) { - if( !this.isOn ) + if( !isOn ) { // We're not on and had no command, but we had work queued. This should never happen, so clear // the event queue just in case. - this.eventQueue.clear(); + eventQueue.clear(); return; } - event = this.eventQueue.poll(); + event = eventQueue.poll(); } } @@ -429,170 +586,52 @@ final class ComputerExecutor switch( command ) { case TURN_ON: - if( this.isOn ) - { - return; - } - this.turnOn(); + if( isOn ) return; + turnOn(); break; case SHUTDOWN: - if( !this.isOn ) - { - return; - } - this.computer.getTerminal() - .reset(); - this.shutdown(); + if( !isOn ) return; + computer.getTerminal().reset(); + shutdown(); break; case REBOOT: - if( !this.isOn ) - { - return; - } - this.computer.getTerminal() - .reset(); - this.shutdown(); + if( !isOn ) return; + computer.getTerminal().reset(); + shutdown(); - this.computer.turnOn(); + computer.turnOn(); break; case ABORT: - if( !this.isOn ) - { - return; - } - this.displayFailure( "Error running computer", TimeoutState.ABORT_MESSAGE ); - this.shutdown(); + if( !isOn ) return; + displayFailure( "Error running computer", TimeoutState.ABORT_MESSAGE ); + shutdown(); + break; + + case ERROR: + if( !isOn ) return; + displayFailure( "Error running computer", "An internal error occurred, see logs." ); + shutdown(); break; } } else if( event != null ) { - this.resumeMachine( event.name, event.args ); - } - } - - private void resumeMachine( String event, Object[] args ) throws InterruptedException - { - MachineResult result = this.machine.handleEvent( event, args ); - this.interruptedEvent = result.isPause(); - if( !result.isError() ) - { - return; - } - - this.displayFailure( "Error running computer", result.getMessage() ); - this.shutdown(); - } - - private void turnOn() throws InterruptedException - { - this.isOnLock.lockInterruptibly(); - try - { - // Reset the terminal and event queue - this.computer.getTerminal() - .reset(); - this.interruptedEvent = false; - synchronized( this.queueLock ) - { - this.eventQueue.clear(); - } - - // Init filesystem - if( (this.fileSystem = this.createFileSystem()) == null ) - { - this.shutdown(); - return; - } - - // Init APIs - this.computer.getEnvironment() - .reset(); - for( ILuaAPI api : this.apis ) - { - api.startup(); - } - - // Init lua - if( (this.machine = this.createLuaMachine()) == null ) - { - this.shutdown(); - return; - } - - // Initialisation has finished, so let's mark ourselves as on. - this.isOn = true; - this.computer.markChanged(); - } - finally - { - this.isOnLock.unlock(); - } - - // Now actually start the computer, now that everything is set up. - this.resumeMachine( null, null ); - } - - private void shutdown() throws InterruptedException - { - this.isOnLock.lockInterruptibly(); - try - { - this.isOn = false; - this.interruptedEvent = false; - synchronized( this.queueLock ) - { - this.eventQueue.clear(); - } - - // Shutdown Lua machine - if( this.machine != null ) - { - this.machine.close(); - this.machine = null; - } - - // Shutdown our APIs - for( ILuaAPI api : this.apis ) - { - api.shutdown(); - } - this.computer.getEnvironment() - .reset(); - - // Unload filesystem - if( this.fileSystem != null ) - { - this.fileSystem.close(); - this.fileSystem = null; - } - - this.computer.getEnvironment() - .resetOutput(); - this.computer.markChanged(); - } - finally - { - this.isOnLock.unlock(); + resumeMachine( event.name, event.args ); } } private void displayFailure( String message, String extra ) { - Terminal terminal = this.computer.getTerminal(); - boolean colour = this.computer.getComputerEnvironment() - .isColour(); + Terminal terminal = computer.getTerminal(); + boolean colour = computer.getComputerEnvironment().isColour(); terminal.reset(); // Display our primary error message - if( colour ) - { - terminal.setTextColour( 15 - Colour.RED.ordinal() ); - } + if( colour ) terminal.setTextColour( 15 - Colour.RED.ordinal() ); terminal.write( message ); if( extra != null ) @@ -605,105 +644,27 @@ final class ComputerExecutor // And display our generic "CC may be installed incorrectly" message. terminal.setCursorPos( 0, terminal.getCursorY() + 1 ); - if( colour ) - { - terminal.setTextColour( 15 - Colour.WHITE.ordinal() ); - } + if( colour ) terminal.setTextColour( 15 - Colour.WHITE.ordinal() ); terminal.write( "ComputerCraft may be installed incorrectly" ); } - private FileSystem createFileSystem() + private void resumeMachine( String event, Object[] args ) throws InterruptedException { - FileSystem filesystem = null; - try - { - filesystem = new FileSystem( "hdd", this.getRootMount() ); + MachineResult result = machine.handleEvent( event, args ); + interruptedEvent = result.isPause(); + if( !result.isError() ) return; - IMount romMount = this.getRomMount(); - if( romMount == null ) - { - this.displayFailure( "Cannot mount ROM", null ); - return null; - } - - filesystem.mount( "rom", "rom", romMount ); - return filesystem; - } - catch( FileSystemException e ) - { - if( filesystem != null ) - { - filesystem.close(); - } - ComputerCraft.log.error( "Cannot mount computer filesystem", e ); - - this.displayFailure( "Cannot mount computer system", null ); - return null; - } - } - - private ILuaMachine createLuaMachine() - { - // Load the bios resource - InputStream biosStream = null; - try - { - biosStream = this.computer.getComputerEnvironment() - .createResourceFile( "computercraft", "lua/bios.lua" ); - } - catch( Exception ignored ) - { - } - - if( biosStream == null ) - { - this.displayFailure( "Error loading bios.lua", null ); - return null; - } - - // Create the lua machine - ILuaMachine machine = new CobaltLuaMachine( this.computer, this.timeout ); - - // Add the APIs. We unwrap them (yes, this is horrible) to get access to the underlying object. - for( ILuaAPI api : this.apis ) - { - machine.addAPI( api instanceof ApiWrapper ? ((ApiWrapper) api).getDelegate() : api ); - } - - // Start the machine running the bios resource - MachineResult result = machine.loadBios( biosStream ); - IoUtil.closeQuietly( biosStream ); - - if( result.isError() ) - { - machine.close(); - this.displayFailure( "Error loading bios.lua", result.getMessage() ); - return null; - } - - return machine; - } - - private IWritableMount getRootMount() - { - if( this.rootMount == null ) - { - this.rootMount = this.computer.getComputerEnvironment() - .createSaveDirMount( "computer/" + this.computer.assignID(), this.computer.getComputerEnvironment() - .getComputerSpaceLimit() ); - } - return this.rootMount; - } - - private IMount getRomMount() - { - return this.computer.getComputerEnvironment() - .createResourceMount( "computercraft", "lua/rom" ); + displayFailure( "Error running computer", result.getMessage() ); + shutdown(); } private enum StateCommand { - TURN_ON, SHUTDOWN, REBOOT, ABORT, + TURN_ON, + SHUTDOWN, + REBOOT, + ABORT, + ERROR, } private static final class Event diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerSide.java b/src/main/java/dan200/computercraft/core/computer/ComputerSide.java index fbc4b054e..dd925b324 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerSide.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerSide.java @@ -3,27 +3,27 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; +import net.minecraft.util.math.Direction; + import javax.annotation.Nonnull; import javax.annotation.Nullable; /** - * A side on a computer. Unlike {@link Direction}, this is relative to the direction the computer is facing.. + * A side on a computer. Unlike {@link Direction}, this is relative to the direction the computer is + * facing.. */ public enum ComputerSide { - BOTTOM( "bottom" ), TOP( "top" ), BACK( "back" ), FRONT( "front" ), RIGHT( "right" ), LEFT( "left" ); + BOTTOM( "bottom" ), + TOP( "top" ), + BACK( "back" ), + FRONT( "front" ), + RIGHT( "right" ), + LEFT( "left" ); - public static final String[] NAMES = new String[] { - "bottom", - "top", - "back", - "front", - "right", - "left" - }; + public static final String[] NAMES = new String[] { "bottom", "top", "back", "front", "right", "left" }; public static final int COUNT = 6; @@ -47,10 +47,7 @@ public enum ComputerSide { for( ComputerSide side : VALUES ) { - if( side.name.equalsIgnoreCase( name ) ) - { - return side; - } + if( side.name.equalsIgnoreCase( name ) ) return side; } return null; @@ -58,6 +55,6 @@ public enum ComputerSide public String getName() { - return this.name; + return name; } } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java b/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java index bdff606db..9747f27e4 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerSystem.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.api.filesystem.IFileSystem; @@ -44,6 +43,21 @@ public class ComputerSystem extends ComputerAccess implements IComputerSystem return "computer"; } + @Nullable + @Override + public IFileSystem getFileSystem() + { + FileSystem fs = environment.getFileSystem(); + return fs == null ? null : fs.getMountWrapper(); + } + + @Nullable + @Override + public String getLabel() + { + return environment.getLabel(); + } + @Nonnull @Override public Map getAvailablePeripherals() @@ -58,19 +72,4 @@ public class ComputerSystem extends ComputerAccess implements IComputerSystem { return null; } - - @Nullable - @Override - public IFileSystem getFileSystem() - { - FileSystem fs = this.environment.getFileSystem(); - return fs == null ? null : fs.getMountWrapper(); - } - - @Nullable - @Override - public String getLabel() - { - return this.environment.getLabel(); - } } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java index 135efd9b0..d190dfefb 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.ComputerCraft; @@ -25,20 +24,24 @@ import static dan200.computercraft.core.computer.TimeoutState.TIMEOUT; /** * Responsible for running all tasks from a {@link Computer}. * - * This is split into two components: the {@link TaskRunner}s, which pull an executor from the queue and execute it, and a single {@link Monitor} which - * observes all runners and kills them if they have not been terminated by {@link TimeoutState#isSoftAborted()}. + * This is split into two components: the {@link TaskRunner}s, which pull an executor from the queue and execute it, and + * a single {@link Monitor} which observes all runners and kills them if they have not been terminated by + * {@link TimeoutState#isSoftAborted()}. * - * Computers are executed using a priority system, with those who have spent less time executing having a higher priority than those hogging the thread. - * This, combined with {@link TimeoutState#isPaused()} means we can reduce the risk of badly behaved computers stalling execution for everyone else. + * Computers are executed using a priority system, with those who have spent less time executing having a higher + * priority than those hogging the thread. This, combined with {@link TimeoutState#isPaused()} means we can reduce the + * risk of badly behaved computers stalling execution for everyone else. * - * This is done using an implementation of Linux's Completely Fair Scheduler. When a computer executes, we compute what share of execution time it has used - * (time executed/number of tasks). We then pick the computer who has the least "virtual execution time" (aka {@link ComputerExecutor#virtualRuntime}). + * This is done using an implementation of Linux's Completely Fair Scheduler. When a computer executes, we compute what + * share of execution time it has used (time executed/number of tasks). We then pick the computer who has the least + * "virtual execution time" (aka {@link ComputerExecutor#virtualRuntime}). * - * When adding a computer to the queue, we make sure its "virtual runtime" is at least as big as the smallest runtime. This means that adding computers - * which have slept a lot do not then have massive priority over everyone else. See {@link #queue(ComputerExecutor)} for how this is implemented. + * When adding a computer to the queue, we make sure its "virtual runtime" is at least as big as the smallest runtime. + * This means that adding computers which have slept a lot do not then have massive priority over everyone else. See + * {@link #queue(ComputerExecutor)} for how this is implemented. * - * In reality, it's unlikely that more than a few computers are waiting to execute at once, so this will not have much effect unless you have a computer - * hogging execution time. However, it is pretty effective in those situations. + * In reality, it's unlikely that more than a few computers are waiting to execute at once, so this will not have much + * effect unless you have a computer hogging execution time. However, it is pretty effective in those situations. * * @see TimeoutState For how hard timeouts are handled. * @see ComputerExecutor For how computers actually do execution. @@ -55,15 +58,16 @@ public final class ComputerThread /** * The target latency between executing two tasks on a single machine. * - * An average tick takes 50ms, and so we ideally need to have handled a couple of events within that window in order to have a perceived low latency. + * An average tick takes 50ms, and so we ideally need to have handled a couple of events within that window in order + * to have a perceived low latency. */ private static final long DEFAULT_LATENCY = TimeUnit.MILLISECONDS.toNanos( 50 ); /** * The minimum value that {@link #DEFAULT_LATENCY} can have when scaled. * - * From statistics gathered on SwitchCraft, almost all machines will execute under 15ms, 75% under 1.5ms, with the mean being about 3ms. Most computers - * shouldn't be too impacted with having such a short period to execute in. + * From statistics gathered on SwitchCraft, almost all machines will execute under 15ms, 75% under 1.5ms, with the + * mean being about 3ms. Most computers shouldn't be too impacted with having such a short period to execute in. */ private static final long DEFAULT_MIN_PERIOD = TimeUnit.MILLISECONDS.toNanos( 5 ); @@ -76,45 +80,48 @@ public final class ComputerThread * Lock used for modifications to the array of current threads. */ private static final Object threadLock = new Object(); - private static final ReentrantLock computerLock = new ReentrantLock(); - private static final Condition hasWork = computerLock.newCondition(); - /** - * Active queues to execute. - */ - private static final TreeSet computerQueue = new TreeSet<>( ( a, b ) -> { - if( a == b ) - { - return 0; // Should never happen, but let's be consistent here - } - long at = a.virtualRuntime, bt = b.virtualRuntime; - if( at == bt ) - { - return Integer.compare( a.hashCode(), b.hashCode() ); - } - return at < bt ? -1 : 1; - } ); - private static final ThreadFactory monitorFactory = ThreadUtils.factory( "Computer-Monitor" ); - private static final ThreadFactory runnerFactory = ThreadUtils.factory( "Computer-Runner" ); /** * Whether the computer thread system is currently running. */ private static volatile boolean running = false; + /** * The current task manager. */ private static Thread monitor; + /** * The array of current runners, and their owning threads. */ private static TaskRunner[] runners; + private static long latency; private static long minPeriod; + + private static final ReentrantLock computerLock = new ReentrantLock(); + + private static final Condition hasWork = computerLock.newCondition(); + + /** + * Active queues to execute. + */ + private static final TreeSet computerQueue = new TreeSet<>( ( a, b ) -> { + if( a == b ) return 0; // Should never happen, but let's be consistent here + + long at = a.virtualRuntime, bt = b.virtualRuntime; + if( at == bt ) return Integer.compare( a.hashCode(), b.hashCode() ); + return at < bt ? -1 : 1; + } ); + /** * The minimum {@link ComputerExecutor#virtualRuntime} time on the tree. */ private static long minimumVirtualRuntime = 0; + private static final ThreadFactory monitorFactory = ThreadUtils.factory( "Computer-Monitor" ); + private static final ThreadFactory runnerFactory = ThreadUtils.factory( "Computer-Runner" ); + private ComputerThread() {} /** @@ -144,20 +151,13 @@ public final class ComputerThread if( runner == null || runner.owner == null || !runner.owner.isAlive() ) { // Mark the old runner as dead, just in case. - if( runner != null ) - { - runner.running = false; - } + if( runner != null ) runner.running = false; // And start a new runner - runnerFactory.newThread( runners[i] = new TaskRunner() ) - .start(); + runnerFactory.newThread( runners[i] = new TaskRunner() ).start(); } } - if( monitor == null || !monitor.isAlive() ) - { - (monitor = monitorFactory.newThread( new Monitor() )).start(); - } + if( monitor == null || !monitor.isAlive() ) (monitor = monitorFactory.newThread( new Monitor() )).start(); } } @@ -173,16 +173,10 @@ public final class ComputerThread { for( TaskRunner runner : runners ) { - if( runner == null ) - { - continue; - } + if( runner == null ) continue; runner.running = false; - if( runner.owner != null ) - { - runner.owner.interrupt(); - } + if( runner.owner != null ) runner.owner.interrupt(); } } } @@ -201,7 +195,8 @@ public final class ComputerThread /** * Mark a computer as having work, enqueuing it on the thread. * - * You must be holding {@link ComputerExecutor}'s {@code queueLock} when calling this method - it should only be called from {@code enqueue}. + * You must be holding {@link ComputerExecutor}'s {@code queueLock} when calling this method - it should only + * be called from {@code enqueue}. * * @param executor The computer to execute work on. */ @@ -210,10 +205,7 @@ public final class ComputerThread computerLock.lock(); try { - if( executor.onComputerQueue ) - { - throw new IllegalStateException( "Cannot queue already queued executor" ); - } + if( executor.onComputerQueue ) throw new IllegalStateException( "Cannot queue already queued executor" ); executor.onComputerQueue = true; updateRuntimes( null ); @@ -247,8 +239,8 @@ public final class ComputerThread /** - * Update the {@link ComputerExecutor#virtualRuntime}s of all running tasks, and then update the {@link #minimumVirtualRuntime} based on the current - * tasks. + * Update the {@link ComputerExecutor#virtualRuntime}s of all running tasks, and then update the + * {@link #minimumVirtualRuntime} based on the current tasks. * * This is called before queueing tasks, to ensure that {@link #minimumVirtualRuntime} is up-to-date. * @@ -259,10 +251,7 @@ public final class ComputerThread long minRuntime = Long.MAX_VALUE; // If we've a task on the queue, use that as our base time. - if( !computerQueue.isEmpty() ) - { - minRuntime = computerQueue.first().virtualRuntime; - } + if( !computerQueue.isEmpty() ) minRuntime = computerQueue.first().virtualRuntime; // Update all the currently executing tasks long now = System.nanoTime(); @@ -272,15 +261,9 @@ public final class ComputerThread { for( TaskRunner runner : currentRunners ) { - if( runner == null ) - { - continue; - } + if( runner == null ) continue; ComputerExecutor executor = runner.currentExecutor.get(); - if( executor == null ) - { - continue; - } + if( executor == null ) continue; // We do two things here: first we update the task's virtual runtime based on when we // last checked, and then we check the minimum. @@ -301,6 +284,43 @@ public final class ComputerThread } } + /** + * Ensure the "currently working" state of the executor is reset, the timings are updated, and then requeue the + * executor if needed. + * + * @param runner The runner this task was on. + * @param executor The executor to requeue + */ + private static void afterWork( TaskRunner runner, ComputerExecutor executor ) + { + // Clear the executor's thread. + Thread currentThread = executor.executingThread.getAndSet( null ); + if( currentThread != runner.owner ) + { + ComputerCraft.log.error( + "Expected computer #{} to be running on {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.", + executor.getComputer().getID(), runner.owner.getName(), currentThread == null ? "nothing" : currentThread.getName() + ); + } + + computerLock.lock(); + try + { + updateRuntimes( executor ); + + // If we've no more tasks, just return. + if( !executor.afterWork() ) return; + + // Otherwise, add to the queue, and signal any waiting workers. + computerQueue.add( executor ); + hasWork.signal(); + } + finally + { + computerLock.unlock(); + } + } + /** * The scaled period for a single task. * @@ -316,47 +336,6 @@ public final class ComputerThread return count < LATENCY_MAX_TASKS ? latency / count : minPeriod; } - /** - * Ensure the "currently working" state of the executor is reset, the timings are updated, and then requeue the executor if needed. - * - * @param runner The runner this task was on. - * @param executor The executor to requeue - */ - private static void afterWork( TaskRunner runner, ComputerExecutor executor ) - { - // Clear the executor's thread. - Thread currentThread = executor.executingThread.getAndSet( null ); - if( currentThread != runner.owner ) - { - ComputerCraft.log.error( - "Expected computer #{} to be running on {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.", - executor.getComputer() - .getID(), - runner.owner.getName(), - currentThread == null ? "nothing" : currentThread.getName() ); - } - - computerLock.lock(); - try - { - updateRuntimes( executor ); - - // If we've no more tasks, just return. - if( !executor.afterWork() ) - { - return; - } - - // Otherwise, add to the queue, and signal any waiting workers. - computerQueue.add( executor ); - hasWork.signal(); - } - finally - { - computerLock.unlock(); - } - } - /** * Determine if the thread has computers queued up. * @@ -367,40 +346,9 @@ public final class ComputerThread return !computerQueue.isEmpty(); } - private static void timeoutTask( ComputerExecutor executor, Thread thread, long time ) - { - if( !ComputerCraft.logComputerErrors ) - { - return; - } - - StringBuilder builder = new StringBuilder().append( "Terminating computer #" ) - .append( executor.getComputer() - .getID() ) - .append( " due to timeout (running for " ) - .append( time * 1e-9 ) - .append( " seconds). This is NOT a bug, but may mean a computer is misbehaving. " ) - .append( thread.getName() ) - .append( " is currently " ) - .append( thread.getState() ); - Object blocking = LockSupport.getBlocker( thread ); - if( blocking != null ) - { - builder.append( "\n on " ) - .append( blocking ); - } - - for( StackTraceElement element : thread.getStackTrace() ) - { - builder.append( "\n at " ) - .append( element ); - } - - ComputerCraft.log.warn( builder.toString() ); - } - /** - * Observes all currently active {@link TaskRunner}s and terminates their tasks once they have exceeded the hard abort limit. + * Observes all currently active {@link TaskRunner}s and terminates their tasks once they have exceeded the hard + * abort limit. * * @see TimeoutState */ @@ -424,37 +372,24 @@ public final class ComputerThread // If we've no runner, skip. if( runner == null || runner.owner == null || !runner.owner.isAlive() ) { - if( !running ) - { - continue; - } + if( !running ) continue; // Mark the old runner as dead and start a new one. ComputerCraft.log.warn( "Previous runner ({}) has crashed, restarting!", runner != null && runner.owner != null ? runner.owner.getName() : runner ); - if( runner != null ) - { - runner.running = false; - } - runnerFactory.newThread( runners[i] = new TaskRunner() ) - .start(); + if( runner != null ) runner.running = false; + runnerFactory.newThread( runners[i] = new TaskRunner() ).start(); } // If the runner has no work, skip ComputerExecutor executor = runner.currentExecutor.get(); - if( executor == null ) - { - continue; - } + if( executor == null ) continue; // If we're still within normal execution times (TIMEOUT) or soft abort (ABORT_TIMEOUT), // then we can let the Lua machine do its work. long afterStart = executor.timeout.nanoCumulative(); long afterHardAbort = afterStart - TIMEOUT - ABORT_TIMEOUT; - if( afterHardAbort < 0 ) - { - continue; - } + if( afterHardAbort < 0 ) continue; // Set the hard abort flag. executor.timeout.hardAbort(); @@ -469,17 +404,13 @@ public final class ComputerThread runner.owner.interrupt(); ComputerExecutor thisExecutor = runner.currentExecutor.getAndSet( null ); - if( thisExecutor != null ) - { - afterWork( runner, executor ); - } + if( thisExecutor != null ) afterWork( runner, executor ); synchronized( threadLock ) { if( running && runners.length > i && runners[i] == runner ) { - runnerFactory.newThread( currentRunners[i] = new TaskRunner() ) - .start(); + runnerFactory.newThread( currentRunners[i] = new TaskRunner() ).start(); } } } @@ -503,22 +434,24 @@ public final class ComputerThread /** * Pulls tasks from the {@link #computerQueue} queue and runs them. * - * This is responsible for running the {@link ComputerExecutor#work()}, {@link ComputerExecutor#beforeWork()} and {@link ComputerExecutor#afterWork()} - * functions. Everything else is either handled by the executor, timeout state or monitor. + * This is responsible for running the {@link ComputerExecutor#work()}, {@link ComputerExecutor#beforeWork()} and + * {@link ComputerExecutor#afterWork()} functions. Everything else is either handled by the executor, timeout + * state or monitor. */ private static final class TaskRunner implements Runnable { - final AtomicReference currentExecutor = new AtomicReference<>(); Thread owner; volatile boolean running = true; + final AtomicReference currentExecutor = new AtomicReference<>(); + @Override public void run() { - this.owner = Thread.currentThread(); + owner = Thread.currentThread(); tasks: - while( this.running && ComputerThread.running ) + while( running && ComputerThread.running ) { // Wait for an active queue to execute ComputerExecutor executor; @@ -527,10 +460,7 @@ public final class ComputerThread computerLock.lockInterruptibly(); try { - while( computerQueue.isEmpty() ) - { - hasWork.await(); - } + while( computerQueue.isEmpty() ) hasWork.await(); executor = computerQueue.pollFirst(); assert executor != null : "hasWork should ensure we never receive null work"; } @@ -548,16 +478,15 @@ public final class ComputerThread // If we're trying to executing some task on this computer while someone else is doing work, something // is seriously wrong. - while( !executor.executingThread.compareAndSet( null, this.owner ) ) + while( !executor.executingThread.compareAndSet( null, owner ) ) { Thread existing = executor.executingThread.get(); if( existing != null ) { ComputerCraft.log.error( "Trying to run computer #{} on thread {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.", - executor.getComputer() - .getID(), this.owner.getName(), - existing.getName() ); + executor.getComputer().getID(), owner.getName(), existing.getName() + ); continue tasks; } } @@ -567,7 +496,7 @@ public final class ComputerThread // And then set the current executor. It's important to do it afterwards, as otherwise we introduce // race conditions with the monitor. - this.currentExecutor.set( executor ); + currentExecutor.set( executor ); // Execute the task try @@ -576,18 +505,38 @@ public final class ComputerThread } catch( Exception | LinkageError | VirtualMachineError e ) { - ComputerCraft.log.error( "Error running task on computer #" + executor.getComputer() - .getID(), e ); + ComputerCraft.log.error( "Error running task on computer #" + executor.getComputer().getID(), e ); + // Tear down the computer immediately. There's no guarantee it's well behaved from now on. + executor.fastFail(); } finally { - ComputerExecutor thisExecutor = this.currentExecutor.getAndSet( null ); - if( thisExecutor != null ) - { - afterWork( this, executor ); - } + ComputerExecutor thisExecutor = currentExecutor.getAndSet( null ); + if( thisExecutor != null ) afterWork( this, executor ); } } } } + + private static void timeoutTask( ComputerExecutor executor, Thread thread, long time ) + { + if( !ComputerCraft.logComputerErrors ) return; + + StringBuilder builder = new StringBuilder() + .append( "Terminating computer #" ).append( executor.getComputer().getID() ) + .append( " due to timeout (running for " ).append( time * 1e-9 ) + .append( " seconds). This is NOT a bug, but may mean a computer is misbehaving. " ) + .append( thread.getName() ) + .append( " is currently " ) + .append( thread.getState() ); + Object blocking = LockSupport.getBlocker( thread ); + if( blocking != null ) builder.append( "\n on " ).append( blocking ); + + for( StackTraceElement element : thread.getStackTrace() ) + { + builder.append( "\n at " ).append( element ); + } + + ComputerCraft.log.warn( builder.toString() ); + } } diff --git a/src/main/java/dan200/computercraft/core/computer/Environment.java b/src/main/java/dan200/computercraft/core/computer/Environment.java index 31b21539c..3931629f1 100644 --- a/src/main/java/dan200/computercraft/core/computer/Environment.java +++ b/src/main/java/dan200/computercraft/core/computer/Environment.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.api.lua.ILuaAPI; @@ -43,17 +42,22 @@ import java.util.Iterator; public final class Environment implements IAPIEnvironment { private final Computer computer; + + private boolean internalOutputChanged = false; private final int[] internalOutput = new int[ComputerSide.COUNT]; private final int[] internalBundledOutput = new int[ComputerSide.COUNT]; + private final int[] externalOutput = new int[ComputerSide.COUNT]; private final int[] externalBundledOutput = new int[ComputerSide.COUNT]; + + private boolean inputChanged = false; private final int[] input = new int[ComputerSide.COUNT]; private final int[] bundledInput = new int[ComputerSide.COUNT]; + private final IPeripheral[] peripherals = new IPeripheral[ComputerSide.COUNT]; - private final Int2ObjectMap timers = new Int2ObjectOpenHashMap<>(); - private boolean internalOutputChanged = false; - private boolean inputChanged = false; private IPeripheralChangeListener peripheralListener = null; + + private final Int2ObjectMap timers = new Int2ObjectOpenHashMap<>(); private int nextTimerToken = 0; Environment( Computer computer ) @@ -64,64 +68,76 @@ public final class Environment implements IAPIEnvironment @Override public int getComputerID() { - return this.computer.assignID(); + return computer.assignID(); } @Nonnull @Override public IComputerEnvironment getComputerEnvironment() { - return this.computer.getComputerEnvironment(); + return computer.getComputerEnvironment(); } @Nonnull @Override public IWorkMonitor getMainThreadMonitor() { - return this.computer.getMainThreadMonitor(); + return computer.getMainThreadMonitor(); } @Nonnull @Override public Terminal getTerminal() { - return this.computer.getTerminal(); + return computer.getTerminal(); } @Override public FileSystem getFileSystem() { - return this.computer.getFileSystem(); + return computer.getFileSystem(); } @Override public void shutdown() { - this.computer.shutdown(); + computer.shutdown(); } @Override public void reboot() { - this.computer.reboot(); + computer.reboot(); } @Override public void queueEvent( String event, Object... args ) { - this.computer.queueEvent( event, args ); + computer.queueEvent( event, args ); + } + + @Override + public int getInput( ComputerSide side ) + { + return input[side.ordinal()]; + } + + @Override + public int getBundledInput( ComputerSide side ) + { + return bundledInput[side.ordinal()]; } @Override public void setOutput( ComputerSide side, int output ) { int index = side.ordinal(); - synchronized( this.internalOutput ) + synchronized( internalOutput ) { - if( this.internalOutput[index] != output ) + if( internalOutput[index] != output ) { - this.internalOutput[index] = output; - this.internalOutputChanged = true; + internalOutput[index] = output; + internalOutputChanged = true; } } } @@ -129,28 +145,22 @@ public final class Environment implements IAPIEnvironment @Override public int getOutput( ComputerSide side ) { - synchronized( this.internalOutput ) + synchronized( internalOutput ) { - return this.computer.isOn() ? this.internalOutput[side.ordinal()] : 0; + return computer.isOn() ? internalOutput[side.ordinal()] : 0; } } - @Override - public int getInput( ComputerSide side ) - { - return this.input[side.ordinal()]; - } - @Override public void setBundledOutput( ComputerSide side, int output ) { int index = side.ordinal(); - synchronized( this.internalOutput ) + synchronized( internalOutput ) { - if( this.internalBundledOutput[index] != output ) + if( internalBundledOutput[index] != output ) { - this.internalBundledOutput[index] = output; - this.internalOutputChanged = true; + internalBundledOutput[index] = output; + internalOutputChanged = true; } } } @@ -158,100 +168,39 @@ public final class Environment implements IAPIEnvironment @Override public int getBundledOutput( ComputerSide side ) { - synchronized( this.internalOutput ) + synchronized( internalOutput ) { - return this.computer.isOn() ? this.internalBundledOutput[side.ordinal()] : 0; + return computer.isOn() ? internalBundledOutput[side.ordinal()] : 0; } } - @Override - public int getBundledInput( ComputerSide side ) - { - return this.bundledInput[side.ordinal()]; - } - - @Override - public void setPeripheralChangeListener( IPeripheralChangeListener listener ) - { - synchronized( this.peripherals ) - { - this.peripheralListener = listener; - } - } - - @Override - public IPeripheral getPeripheral( ComputerSide side ) - { - synchronized( this.peripherals ) - { - return this.peripherals[side.ordinal()]; - } - } - - @Override - public String getLabel() - { - return this.computer.getLabel(); - } - - @Override - public void setLabel( String label ) - { - this.computer.setLabel( label ); - } - - @Override - public int startTimer( long ticks ) - { - synchronized( this.timers ) - { - this.timers.put( this.nextTimerToken, new Timer( ticks ) ); - return this.nextTimerToken++; - } - } - - @Override - public void cancelTimer( int id ) - { - synchronized( this.timers ) - { - this.timers.remove( id ); - } - } - - @Override - public void addTrackingChange( @Nonnull TrackingField field, long change ) - { - Tracking.addValue( this.computer, field, change ); - } - public int getExternalRedstoneOutput( ComputerSide side ) { - return this.computer.isOn() ? this.externalOutput[side.ordinal()] : 0; + return computer.isOn() ? externalOutput[side.ordinal()] : 0; } public int getExternalBundledRedstoneOutput( ComputerSide side ) { - return this.computer.isOn() ? this.externalBundledOutput[side.ordinal()] : 0; + return computer.isOn() ? externalBundledOutput[side.ordinal()] : 0; } public void setRedstoneInput( ComputerSide side, int level ) { int index = side.ordinal(); - if( this.input[index] != level ) + if( input[index] != level ) { - this.input[index] = level; - this.inputChanged = true; + input[index] = level; + inputChanged = true; } } public void setBundledRedstoneInput( ComputerSide side, int combination ) { int index = side.ordinal(); - if( this.bundledInput[index] != combination ) + if( bundledInput[index] != combination ) { - this.bundledInput[index] = combination; - this.inputChanged = true; + bundledInput[index] = combination; + inputChanged = true; } } @@ -263,9 +212,9 @@ public final class Environment implements IAPIEnvironment */ void reset() { - synchronized( this.timers ) + synchronized( timers ) { - this.timers.clear(); + timers.clear(); } } @@ -274,17 +223,16 @@ public final class Environment implements IAPIEnvironment */ void tick() { - if( this.inputChanged ) + if( inputChanged ) { - this.inputChanged = false; - this.queueEvent( "redstone" ); + inputChanged = false; + queueEvent( "redstone" ); } - synchronized( this.timers ) + synchronized( timers ) { // Countdown all of our active timers - Iterator> it = this.timers.int2ObjectEntrySet() - .iterator(); + Iterator> it = timers.int2ObjectEntrySet().iterator(); while( it.hasNext() ) { Int2ObjectMap.Entry entry = it.next(); @@ -293,7 +241,7 @@ public final class Environment implements IAPIEnvironment if( timer.ticksLeft <= 0 ) { // Queue the "timer" event - this.queueEvent( TIMER_EVENT, entry.getIntKey() ); + queueEvent( TIMER_EVENT, entry.getIntKey() ); it.remove(); } } @@ -308,31 +256,28 @@ public final class Environment implements IAPIEnvironment boolean updateOutput() { // Mark output as changed if the internal redstone has changed - synchronized( this.internalOutput ) + synchronized( internalOutput ) { - if( !this.internalOutputChanged ) - { - return false; - } + if( !internalOutputChanged ) return false; boolean changed = false; for( int i = 0; i < ComputerSide.COUNT; i++ ) { - if( this.externalOutput[i] != this.internalOutput[i] ) + if( externalOutput[i] != internalOutput[i] ) { - this.externalOutput[i] = this.internalOutput[i]; + externalOutput[i] = internalOutput[i]; changed = true; } - if( this.externalBundledOutput[i] != this.internalBundledOutput[i] ) + if( externalBundledOutput[i] != internalBundledOutput[i] ) { - this.externalBundledOutput[i] = this.internalBundledOutput[i]; + externalBundledOutput[i] = internalBundledOutput[i]; changed = true; } } - this.internalOutputChanged = false; + internalOutputChanged = false; return changed; } @@ -341,31 +286,85 @@ public final class Environment implements IAPIEnvironment void resetOutput() { // Reset redstone output - synchronized( this.internalOutput ) + synchronized( internalOutput ) { - Arrays.fill( this.internalOutput, 0 ); - Arrays.fill( this.internalBundledOutput, 0 ); - this.internalOutputChanged = true; + Arrays.fill( internalOutput, 0 ); + Arrays.fill( internalBundledOutput, 0 ); + internalOutputChanged = true; + } + } + + @Override + public IPeripheral getPeripheral( ComputerSide side ) + { + synchronized( peripherals ) + { + return peripherals[side.ordinal()]; } } public void setPeripheral( ComputerSide side, IPeripheral peripheral ) { - synchronized( this.peripherals ) + synchronized( peripherals ) { int index = side.ordinal(); - IPeripheral existing = this.peripherals[index]; - if( (existing == null && peripheral != null) || (existing != null && peripheral == null) || (existing != null && !existing.equals( peripheral )) ) + IPeripheral existing = peripherals[index]; + if( (existing == null && peripheral != null) || + (existing != null && peripheral == null) || + (existing != null && !existing.equals( peripheral )) ) { - this.peripherals[index] = peripheral; - if( this.peripheralListener != null ) - { - this.peripheralListener.onPeripheralChanged( side, peripheral ); - } + peripherals[index] = peripheral; + if( peripheralListener != null ) peripheralListener.onPeripheralChanged( side, peripheral ); } } } + @Override + public void setPeripheralChangeListener( IPeripheralChangeListener listener ) + { + synchronized( peripherals ) + { + peripheralListener = listener; + } + } + + @Override + public String getLabel() + { + return computer.getLabel(); + } + + @Override + public void setLabel( String label ) + { + computer.setLabel( label ); + } + + @Override + public int startTimer( long ticks ) + { + synchronized( timers ) + { + timers.put( nextTimerToken, new Timer( ticks ) ); + return nextTimerToken++; + } + } + + @Override + public void cancelTimer( int id ) + { + synchronized( timers ) + { + timers.remove( id ); + } + } + + @Override + public void addTrackingChange( @Nonnull TrackingField field, long change ) + { + Tracking.addValue( computer, field, change ); + } + private static class Timer { long ticksLeft; diff --git a/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java b/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java index 66487c42b..3d928ffc2 100644 --- a/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java +++ b/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.api.filesystem.IMount; diff --git a/src/main/java/dan200/computercraft/core/computer/MainThread.java b/src/main/java/dan200/computercraft/core/computer/MainThread.java index 0187ff2db..8f53541e2 100644 --- a/src/main/java/dan200/computercraft/core/computer/MainThread.java +++ b/src/main/java/dan200/computercraft/core/computer/MainThread.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.ComputerCraft; @@ -15,16 +14,17 @@ import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; /** - * Runs tasks on the main (server) thread, ticks {@link MainThreadExecutor}s, and limits how much time is used this tick. + * Runs tasks on the main (server) thread, ticks {@link MainThreadExecutor}s, and limits how much time is used this + * tick. * - * Similar to {@link MainThreadExecutor}, the {@link MainThread} can be in one of three states: cool, hot and cooling. However, the implementation here is a - * little different: + * Similar to {@link MainThreadExecutor}, the {@link MainThread} can be in one of three states: cool, hot and cooling. + * However, the implementation here is a little different: * - * {@link MainThread} starts cool, and runs as many tasks as it can in the current {@link #budget}ns. Any external tasks (those run by tile entities, - * etc...) will also consume the budget + * {@link MainThread} starts cool, and runs as many tasks as it can in the current {@link #budget}ns. Any external tasks + * (those run by tile entities, etc...) will also consume the budget * - * Next tick, we put {@link ComputerCraft#maxMainGlobalTime} into our budget (and clamp it to that value to). If we're still over budget, then we should not - * execute any work (either as part of {@link MainThread} or externally). + * Next tick, we put {@link ComputerCraft#maxMainGlobalTime} into our budget (and clamp it to that value to). If we're + * still over budget, then we should not execute any work (either as part of {@link MainThread} or externally). */ public final class MainThread { @@ -40,16 +40,10 @@ public final class MainThread * The queue of {@link MainThreadExecutor}s with tasks to perform. */ private static final TreeSet executors = new TreeSet<>( ( a, b ) -> { - if( a == b ) - { - return 0; // Should never happen, but let's be consistent here - } + if( a == b ) return 0; // Should never happen, but let's be consistent here long at = a.virtualTime, bt = b.virtualTime; - if( at == bt ) - { - return Integer.compare( a.hashCode(), b.hashCode() ); - } + if( at == bt ) return Integer.compare( a.hashCode(), b.hashCode() ); return at < bt ? -1 : 1; } ); @@ -62,7 +56,8 @@ public final class MainThread private static final HashSet cooling = new HashSet<>(); /** - * The current tick number. This is used by {@link MainThreadExecutor} to determine when to reset its own time counter. + * The current tick number. This is used by {@link MainThreadExecutor} to determine when to reset its own time + * counter. * * @see #currentTick() */ @@ -93,10 +88,7 @@ public final class MainThread { synchronized( executors ) { - if( executor.onQueue ) - { - throw new IllegalStateException( "Cannot queue already queued executor" ); - } + if( executor.onQueue ) throw new IllegalStateException( "Cannot queue already queued executor" ); executor.onQueue = true; executor.updateTime(); @@ -105,10 +97,7 @@ public final class MainThread long newRuntime = minimumTime; // Slow down new computers a little bit. - if( executor.virtualTime == 0 ) - { - newRuntime += ComputerCraft.maxMainComputerTime; - } + if( executor.virtualTime == 0 ) newRuntime += ComputerCraft.maxMainComputerTime; executor.virtualTime = Math.max( newRuntime, executor.virtualTime ); @@ -121,6 +110,11 @@ public final class MainThread cooling.add( executor ); } + static void consumeTime( long time ) + { + budget -= time; + } + static boolean canExecute() { return canExecute; @@ -145,10 +139,7 @@ public final class MainThread // Cool down any warm computers. cooling.removeIf( MainThreadExecutor::tickCooling ); - if( !canExecute ) - { - return; - } + if( !canExecute ) return; // Run until we meet the deadline. long start = System.nanoTime(); @@ -160,10 +151,7 @@ public final class MainThread { executor = executors.pollFirst(); } - if( executor == null ) - { - break; - } + if( executor == null ) break; long taskStart = System.nanoTime(); executor.execute(); @@ -171,10 +159,7 @@ public final class MainThread long taskStop = System.nanoTime(); synchronized( executors ) { - if( executor.afterExecute( taskStop - taskStart ) ) - { - executors.add( executor ); - } + if( executor.afterExecute( taskStop - taskStart ) ) executors.add( executor ); // Compute the new minimum time (including the next task on the queue too). Note that this may also include // time spent in external tasks. @@ -182,28 +167,17 @@ public final class MainThread if( !executors.isEmpty() ) { MainThreadExecutor next = executors.first(); - if( next.virtualTime < newMinimum ) - { - newMinimum = next.virtualTime; - } + if( next.virtualTime < newMinimum ) newMinimum = next.virtualTime; } minimumTime = Math.max( minimumTime, newMinimum ); } - if( taskStop >= deadline ) - { - break; - } + if( taskStop >= deadline ) break; } consumeTime( System.nanoTime() - start ); } - static void consumeTime( long time ) - { - budget -= time; - } - public static void reset() { currentTick = 0; diff --git a/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java b/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java index 74be06df7..07737c4c2 100644 --- a/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java +++ b/src/main/java/dan200/computercraft/core/computer/MainThreadExecutor.java @@ -3,13 +3,13 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IWorkMonitor; import dan200.computercraft.core.tracking.Tracking; import dan200.computercraft.shared.turtle.core.TurtleBrain; +import net.minecraft.block.entity.BlockEntity; import javax.annotation.Nonnull; import java.util.ArrayDeque; @@ -17,28 +17,32 @@ import java.util.Queue; import java.util.concurrent.TimeUnit; /** - * Keeps track of tasks that a {@link Computer} should run on the main thread and how long that has been spent executing them. + * Keeps track of tasks that a {@link Computer} should run on the main thread and how long that has been spent executing + * them. * - * This provides rate-limiting mechanism for tasks enqueued with {@link Computer#queueMainThread(Runnable)}, but also those run elsewhere (such as during - * the turtle's tick - see {@link TurtleBrain#update()}). In order to handle this, the executor goes through three stages: + * This provides rate-limiting mechanism for tasks enqueued with {@link Computer#queueMainThread(Runnable)}, but also + * those run elsewhere (such as during the turtle's tick - see {@link TurtleBrain#update()}). In order to handle this, + * the executor goes through three stages: * - * When {@link State#COOL}, the computer is allocated {@link ComputerCraft#maxMainComputerTime}ns to execute any work this tick. At the beginning of the - * tick, we execute as many {@link MainThread} tasks as possible, until our time-frame or the global time frame has expired. + * When {@link State#COOL}, the computer is allocated {@link ComputerCraft#maxMainComputerTime}ns to execute any work + * this tick. At the beginning of the tick, we execute as many {@link MainThread} tasks as possible, until our + * time-frame or the global time frame has expired. * - * Then, when other objects (such as {@link TileEntity}) are ticked, we update how much time we've used using {@link IWorkMonitor#trackWork(long, - * TimeUnit)}. + * Then, when other objects (such as {@link BlockEntity}) are ticked, we update how much time we've used using + * {@link IWorkMonitor#trackWork(long, TimeUnit)}. * - * Now, if anywhere during this period, we use more than our allocated time slice, the executor is marked as {@link State#HOT}. This means it will no longer - * be able to execute {@link MainThread} tasks (though will still execute tile entity tasks, in order to prevent the main thread from exhausting work every - * tick). + * Now, if anywhere during this period, we use more than our allocated time slice, the executor is marked as + * {@link State#HOT}. This means it will no longer be able to execute {@link MainThread} tasks (though will still + * execute tile entity tasks, in order to prevent the main thread from exhausting work every tick). * - * At the beginning of the next tick, we increment the budget e by {@link ComputerCraft#maxMainComputerTime} and any {@link State#HOT} executors are marked - * as {@link State#COOLING}. They will remain cooling until their budget is fully replenished (is equal to {@link ComputerCraft#maxMainComputerTime}). Note, - * this is different to {@link MainThread}, which allows running when it has any budget left. When cooling, no tasks are executed - be they on the - * tile entity or main thread. + * At the beginning of the next tick, we increment the budget e by {@link ComputerCraft#maxMainComputerTime} and any + * {@link State#HOT} executors are marked as {@link State#COOLING}. They will remain cooling until their budget is + * fully replenished (is equal to {@link ComputerCraft#maxMainComputerTime}). Note, this is different to + * {@link MainThread}, which allows running when it has any budget left. When cooling, no tasks are executed - + * be they on the tile entity or main thread. * - * This mechanism means that, on average, computers will use at most {@link ComputerCraft#maxMainComputerTime}ns per second, but one task source will not - * prevent others from executing. + * This mechanism means that, on average, computers will use at most {@link ComputerCraft#maxMainComputerTime}ns per + * second, but one task source will not prevent others from executing. * * @see MainThread * @see IWorkMonitor @@ -55,8 +59,8 @@ final class MainThreadExecutor implements IWorkMonitor private final Computer computer; /** - * A lock used for any changes to {@link #tasks}, or {@link #onQueue}. This will be used on the main thread, so locks should be kept as brief as - * possible. + * A lock used for any changes to {@link #tasks}, or {@link #onQueue}. This will be + * used on the main thread, so locks should be kept as brief as possible. */ private final Object queueLock = new Object(); @@ -77,7 +81,7 @@ final class MainThreadExecutor implements IWorkMonitor * @see #afterExecute(long) */ volatile boolean onQueue; - long virtualTime; + /** * The remaining budgeted time for this tick. This may be negative, in the case that we've gone over budget. * @@ -85,6 +89,7 @@ final class MainThreadExecutor implements IWorkMonitor * @see #consumeTime(long) */ private long budget = 0; + /** * The last tick that {@link #budget} was updated. * @@ -92,14 +97,18 @@ final class MainThreadExecutor implements IWorkMonitor * @see #consumeTime(long) */ private int currentTick = -1; + /** * The current state of this executor. * * @see #canWork() */ private State state = State.COOL; + private long pendingTime; + long virtualTime; + MainThreadExecutor( Computer computer ) { this.computer = computer; @@ -113,37 +122,25 @@ final class MainThreadExecutor implements IWorkMonitor */ boolean enqueue( Runnable runnable ) { - synchronized( this.queueLock ) + synchronized( queueLock ) { - if( this.tasks.size() >= MAX_TASKS || !this.tasks.offer( runnable ) ) - { - return false; - } - if( !this.onQueue && this.state == State.COOL ) - { - MainThread.queue( this, true ); - } + if( tasks.size() >= MAX_TASKS || !tasks.offer( runnable ) ) return false; + if( !onQueue && state == State.COOL ) MainThread.queue( this, true ); return true; } } void execute() { - if( this.state != State.COOL ) - { - return; - } + if( state != State.COOL ) return; Runnable task; - synchronized( this.queueLock ) + synchronized( queueLock ) { - task = this.tasks.poll(); + task = tasks.poll(); } - if( task != null ) - { - task.run(); - } + if( task != null ) task.run(); } /** @@ -154,54 +151,17 @@ final class MainThreadExecutor implements IWorkMonitor */ boolean afterExecute( long time ) { - this.consumeTime( time ); + consumeTime( time ); - synchronized( this.queueLock ) + synchronized( queueLock ) { - this.virtualTime += time; - this.updateTime(); - if( this.state != State.COOL || this.tasks.isEmpty() ) - { - return this.onQueue = false; - } + virtualTime += time; + updateTime(); + if( state != State.COOL || tasks.isEmpty() ) return onQueue = false; return true; } } - private void consumeTime( long time ) - { - Tracking.addServerTiming( this.computer, time ); - - // Reset the budget if moving onto a new tick. We know this is safe, as this will only have happened if - // #tickCooling() isn't called, and so we didn't overrun the previous tick. - if( this.currentTick != MainThread.currentTick() ) - { - this.currentTick = MainThread.currentTick(); - this.budget = ComputerCraft.maxMainComputerTime; - } - - this.budget -= time; - - // If we've gone over our limit, mark us as having to cool down. - if( this.budget < 0 && this.state == State.COOL ) - { - this.state = State.HOT; - MainThread.cooling( this ); - } - } - - void updateTime() - { - this.virtualTime += this.pendingTime; - this.pendingTime = 0; - } - - @Override - public boolean shouldWork() - { - return this.state == State.COOL && MainThread.canExecute(); - } - /** * Whether we should execute "external" tasks (ones not part of {@link #tasks}). * @@ -210,22 +170,50 @@ final class MainThreadExecutor implements IWorkMonitor @Override public boolean canWork() { - return this.state != State.COOLING && MainThread.canExecute(); + return state != State.COOLING && MainThread.canExecute(); + } + + @Override + public boolean shouldWork() + { + return state == State.COOL && MainThread.canExecute(); } @Override public void trackWork( long time, @Nonnull TimeUnit unit ) { long nanoTime = unit.toNanos( time ); - synchronized( this.queueLock ) + synchronized( queueLock ) { - this.pendingTime += nanoTime; + pendingTime += nanoTime; } - this.consumeTime( nanoTime ); + consumeTime( nanoTime ); MainThread.consumeTime( nanoTime ); } + private void consumeTime( long time ) + { + Tracking.addServerTiming( computer, time ); + + // Reset the budget if moving onto a new tick. We know this is safe, as this will only have happened if + // #tickCooling() isn't called, and so we didn't overrun the previous tick. + if( currentTick != MainThread.currentTick() ) + { + currentTick = MainThread.currentTick(); + budget = ComputerCraft.maxMainComputerTime; + } + + budget -= time; + + // If we've gone over our limit, mark us as having to cool down. + if( budget < 0 && state == State.COOL ) + { + state = State.HOT; + MainThread.cooling( this ); + } + } + /** * Move this executor forward one tick, replenishing the budget by {@link ComputerCraft#maxMainComputerTime}. * @@ -233,27 +221,29 @@ final class MainThreadExecutor implements IWorkMonitor */ boolean tickCooling() { - this.state = State.COOLING; - this.currentTick = MainThread.currentTick(); - this.budget = Math.min( this.budget + ComputerCraft.maxMainComputerTime, ComputerCraft.maxMainComputerTime ); - if( this.budget < ComputerCraft.maxMainComputerTime ) - { - return false; - } + state = State.COOLING; + currentTick = MainThread.currentTick(); + budget = Math.min( budget + ComputerCraft.maxMainComputerTime, ComputerCraft.maxMainComputerTime ); + if( budget < ComputerCraft.maxMainComputerTime ) return false; - this.state = State.COOL; - synchronized( this.queueLock ) + state = State.COOL; + synchronized( queueLock ) { - if( !this.tasks.isEmpty() && !this.onQueue ) - { - MainThread.queue( this, false ); - } + if( !tasks.isEmpty() && !onQueue ) MainThread.queue( this, false ); } return true; } + void updateTime() + { + virtualTime += pendingTime; + pendingTime = 0; + } + private enum State { - COOL, HOT, COOLING, + COOL, + HOT, + COOLING, } } diff --git a/src/main/java/dan200/computercraft/core/computer/TimeoutState.java b/src/main/java/dan200/computercraft/core/computer/TimeoutState.java index 550bc59fc..5f2d99265 100644 --- a/src/main/java/dan200/computercraft/core/computer/TimeoutState.java +++ b/src/main/java/dan200/computercraft/core/computer/TimeoutState.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.core.lua.ILuaMachine; @@ -14,18 +13,20 @@ import java.util.concurrent.TimeUnit; /** * Used to measure how long a computer has executed for, and thus the relevant timeout states. * - * Timeouts are mostly used for execution of Lua code: we should ideally never have a state where constructing the APIs or machines themselves takes more - * than a fraction of a second. + * Timeouts are mostly used for execution of Lua code: we should ideally never have a state where constructing the APIs + * or machines themselves takes more than a fraction of a second. * - * When a computer runs, it is allowed to run for 7 seconds ({@link #TIMEOUT}). After that point, the "soft abort" flag is set ({@link #isSoftAborted()}). - * Here, the Lua machine will attempt to abort the program in some safe manner (namely, throwing a "Too long without yielding" error). + * When a computer runs, it is allowed to run for 7 seconds ({@link #TIMEOUT}). After that point, the "soft abort" flag + * is set ({@link #isSoftAborted()}). Here, the Lua machine will attempt to abort the program in some safe manner + * (namely, throwing a "Too long without yielding" error). * - * Now, if a computer still does not stop after that period, they're behaving really badly. 1.5 seconds after a soft abort ({@link #ABORT_TIMEOUT}), we - * trigger a hard abort (note, this is done from the computer thread manager). This will destroy the entire Lua runtime and shut the computer down. + * Now, if a computer still does not stop after that period, they're behaving really badly. 1.5 seconds after a soft + * abort ({@link #ABORT_TIMEOUT}), we trigger a hard abort (note, this is done from the computer thread manager). This + * will destroy the entire Lua runtime and shut the computer down. * - * The Lua runtime is also allowed to pause execution if there are other computers contesting for work. All computers are allowed to run for {@link - * ComputerThread#scaledPeriod()} nanoseconds (see {@link #currentDeadline}). After that period, if any computers are waiting to be executed then we'll set - * the paused flag to true ({@link #isPaused()}. + * The Lua runtime is also allowed to pause execution if there are other computers contesting for work. All computers + * are allowed to run for {@link ComputerThread#scaledPeriod()} nanoseconds (see {@link #currentDeadline}). After that + * period, if any computers are waiting to be executed then we'll set the paused flag to true ({@link #isPaused()}. * * @see ComputerThread * @see ILuaMachine @@ -33,18 +34,21 @@ import java.util.concurrent.TimeUnit; */ public final class TimeoutState { - /** - * The error message to display when we trigger an abort. - */ - public static final String ABORT_MESSAGE = "Too long without yielding"; /** * The total time a task is allowed to run before aborting in nanoseconds. */ static final long TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 7000 ); + /** * The time the task is allowed to run after each abort in nanoseconds. */ static final long ABORT_TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 1500 ); + + /** + * The error message to display when we trigger an abort. + */ + public static final String ABORT_MESSAGE = "Too long without yielding"; + private boolean paused; private boolean softAbort; private volatile boolean hardAbort; @@ -71,12 +75,12 @@ public final class TimeoutState long nanoCumulative() { - return System.nanoTime() - this.cumulativeStart; + return System.nanoTime() - cumulativeStart; } long nanoCurrent() { - return System.nanoTime() - this.currentStart; + return System.nanoTime() - currentStart; } /** @@ -87,26 +91,21 @@ public final class TimeoutState // Important: The weird arithmetic here is important, as nanoTime may return negative values, and so we // need to handle overflow. long now = System.nanoTime(); - if( !this.paused ) - { - this.paused = this.currentDeadline - now <= 0 && ComputerThread.hasPendingWork(); // now >= currentDeadline - } - if( !this.softAbort ) - { - this.softAbort = now - this.cumulativeStart - TIMEOUT >= 0; // now - cumulativeStart >= TIMEOUT - } + if( !paused ) paused = currentDeadline - now <= 0 && ComputerThread.hasPendingWork(); // now >= currentDeadline + if( !softAbort ) softAbort = now - cumulativeStart - TIMEOUT >= 0; // now - cumulativeStart >= TIMEOUT } /** * Whether we should pause execution of this machine. * - * This is determined by whether we've consumed our time slice, and if there are other computers waiting to perform work. + * This is determined by whether we've consumed our time slice, and if there are other computers waiting to perform + * work. * * @return Whether we should pause execution. */ public boolean isPaused() { - return this.paused; + return paused; } /** @@ -116,7 +115,7 @@ public final class TimeoutState */ public boolean isSoftAborted() { - return this.softAbort; + return softAbort; } /** @@ -126,7 +125,7 @@ public final class TimeoutState */ public boolean isHardAborted() { - return this.hardAbort; + return hardAbort; } /** @@ -134,7 +133,7 @@ public final class TimeoutState */ void hardAbort() { - this.softAbort = this.hardAbort = true; + softAbort = hardAbort = true; } /** @@ -143,10 +142,10 @@ public final class TimeoutState void startTimer() { long now = System.nanoTime(); - this.currentStart = now; - this.currentDeadline = now + ComputerThread.scaledPeriod(); + currentStart = now; + currentDeadline = now + ComputerThread.scaledPeriod(); // Compute the "nominal start time". - this.cumulativeStart = now - this.cumulativeElapsed; + cumulativeStart = now - cumulativeElapsed; } /** @@ -157,8 +156,8 @@ public final class TimeoutState void pauseTimer() { // We set the cumulative time to difference between current time and "nominal start time". - this.cumulativeElapsed = System.nanoTime() - this.cumulativeStart; - this.paused = false; + cumulativeElapsed = System.nanoTime() - cumulativeStart; + paused = false; } /** @@ -166,7 +165,7 @@ public final class TimeoutState */ void stopTimer() { - this.cumulativeElapsed = 0; - this.paused = this.softAbort = this.hardAbort = false; + cumulativeElapsed = 0; + paused = softAbort = hardAbort = false; } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java b/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java index 65f4c1250..46e63e9ac 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import dan200.computercraft.api.filesystem.FileOperationException; @@ -20,24 +19,52 @@ import java.util.Set; public class ComboMount implements IMount { - private IMount[] m_parts; + private final IMount[] parts; public ComboMount( IMount[] parts ) { - this.m_parts = parts; + this.parts = parts; } // IMount implementation + @Override + public boolean exists( @Nonnull String path ) throws IOException + { + for( int i = parts.length - 1; i >= 0; --i ) + { + IMount part = parts[i]; + if( part.exists( path ) ) + { + return true; + } + } + return false; + } + + @Override + public boolean isDirectory( @Nonnull String path ) throws IOException + { + for( int i = parts.length - 1; i >= 0; --i ) + { + IMount part = parts[i]; + if( part.isDirectory( path ) ) + { + return true; + } + } + return false; + } + @Override public void list( @Nonnull String path, @Nonnull List contents ) throws IOException { // Combine the lists from all the mounts List foundFiles = null; int foundDirs = 0; - for( int i = this.m_parts.length - 1; i >= 0; --i ) + for( int i = parts.length - 1; i >= 0; --i ) { - IMount part = this.m_parts[i]; + IMount part = parts[i]; if( part.exists( path ) && part.isDirectory( path ) ) { if( foundFiles == null ) @@ -72,13 +99,27 @@ public class ComboMount implements IMount } } + @Override + public long getSize( @Nonnull String path ) throws IOException + { + for( int i = parts.length - 1; i >= 0; --i ) + { + IMount part = parts[i]; + if( part.exists( path ) ) + { + return part.getSize( path ); + } + } + throw new FileOperationException( path, "No such file" ); + } + @Nonnull @Override public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException { - for( int i = this.m_parts.length - 1; i >= 0; --i ) + for( int i = parts.length - 1; i >= 0; --i ) { - IMount part = this.m_parts[i]; + IMount part = parts[i]; if( part.exists( path ) && !part.isDirectory( path ) ) { return part.openForRead( path ); @@ -91,9 +132,9 @@ public class ComboMount implements IMount @Override public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException { - for( int i = this.m_parts.length - 1; i >= 0; --i ) + for( int i = parts.length - 1; i >= 0; --i ) { - IMount part = this.m_parts[i]; + IMount part = parts[i]; if( part.exists( path ) && !part.isDirectory( path ) ) { return part.getAttributes( path ); @@ -101,46 +142,4 @@ public class ComboMount implements IMount } throw new FileOperationException( path, "No such file" ); } - - @Override - public boolean exists( @Nonnull String path ) throws IOException - { - for( int i = this.m_parts.length - 1; i >= 0; --i ) - { - IMount part = this.m_parts[i]; - if( part.exists( path ) ) - { - return true; - } - } - return false; - } - - @Override - public boolean isDirectory( @Nonnull String path ) throws IOException - { - for( int i = this.m_parts.length - 1; i >= 0; --i ) - { - IMount part = this.m_parts[i]; - if( part.isDirectory( path ) ) - { - return true; - } - } - return false; - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - for( int i = this.m_parts.length - 1; i >= 0; --i ) - { - IMount part = this.m_parts[i]; - if( part.exists( path ) ) - { - return part.getSize( path ); - } - } - throw new FileOperationException( path, "No such file" ); - } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java b/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java index 2b3050fe5..ab89d3fb8 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import dan200.computercraft.api.filesystem.FileOperationException; @@ -16,18 +15,6 @@ import java.util.List; public class EmptyMount implements IMount { - @Override - public void list( @Nonnull String path, @Nonnull List contents ) - { - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - throw new FileOperationException( path, "No such file" ); - } - @Override public boolean exists( @Nonnull String path ) { @@ -40,9 +27,21 @@ public class EmptyMount implements IMount return path.isEmpty(); } + @Override + public void list( @Nonnull String path, @Nonnull List contents ) + { + } + @Override public long getSize( @Nonnull String path ) { return 0; } + + @Nonnull + @Override + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + throw new FileOperationException( path, "No such file" ); + } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileMount.java b/src/main/java/dan200/computercraft/core/filesystem/FileMount.java index 37627333d..bcd19adbe 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/FileMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/FileMount.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import com.google.common.collect.Sets; @@ -27,32 +26,383 @@ public class FileMount implements IWritableMount { private static final int MINIMUM_FILE_SIZE = 500; private static final Set READ_OPTIONS = Collections.singleton( StandardOpenOption.READ ); - private static final Set WRITE_OPTIONS = Sets.newHashSet( StandardOpenOption.WRITE, - StandardOpenOption.CREATE, - StandardOpenOption.TRUNCATE_EXISTING ); + private static final Set WRITE_OPTIONS = Sets.newHashSet( StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING ); private static final Set APPEND_OPTIONS = Sets.newHashSet( StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND ); - private File m_rootPath; - private long m_capacity; - private long m_usedSpace; + + private class WritableCountingChannel implements WritableByteChannel + { + + private final WritableByteChannel inner; + long ignoredBytesLeft; + + WritableCountingChannel( WritableByteChannel inner, long bytesToIgnore ) + { + this.inner = inner; + ignoredBytesLeft = bytesToIgnore; + } + + @Override + public int write( @Nonnull ByteBuffer b ) throws IOException + { + count( b.remaining() ); + return inner.write( b ); + } + + void count( long n ) throws IOException + { + ignoredBytesLeft -= n; + if( ignoredBytesLeft < 0 ) + { + long newBytes = -ignoredBytesLeft; + ignoredBytesLeft = 0; + + long bytesLeft = capacity - usedSpace; + if( newBytes > bytesLeft ) throw new IOException( "Out of space" ); + usedSpace += newBytes; + } + } + + @Override + public boolean isOpen() + { + return inner.isOpen(); + } + + @Override + public void close() throws IOException + { + inner.close(); + } + } + + private class SeekableCountingChannel extends WritableCountingChannel implements SeekableByteChannel + { + private final SeekableByteChannel inner; + + SeekableCountingChannel( SeekableByteChannel inner, long bytesToIgnore ) + { + super( inner, bytesToIgnore ); + this.inner = inner; + } + + @Override + public SeekableByteChannel position( long newPosition ) throws IOException + { + if( !isOpen() ) throw new ClosedChannelException(); + if( newPosition < 0 ) + { + throw new IllegalArgumentException( "Cannot seek before the beginning of the stream" ); + } + + long delta = newPosition - inner.position(); + if( delta < 0 ) + { + ignoredBytesLeft -= delta; + } + else + { + count( delta ); + } + + return inner.position( newPosition ); + } + + @Override + public SeekableByteChannel truncate( long size ) throws IOException + { + throw new IOException( "Not yet implemented" ); + } + + @Override + public int read( ByteBuffer dst ) throws ClosedChannelException + { + if( !inner.isOpen() ) throw new ClosedChannelException(); + throw new NonReadableChannelException(); + } + + @Override + public long position() throws IOException + { + return inner.position(); + } + + @Override + public long size() throws IOException + { + return inner.size(); + } + } + + private final File rootPath; + private final long capacity; + private long usedSpace; public FileMount( File rootPath, long capacity ) { - this.m_rootPath = rootPath; - this.m_capacity = capacity + MINIMUM_FILE_SIZE; - this.m_usedSpace = this.created() ? measureUsedSpace( this.m_rootPath ) : MINIMUM_FILE_SIZE; + this.rootPath = rootPath; + this.capacity = capacity + MINIMUM_FILE_SIZE; + usedSpace = created() ? measureUsedSpace( this.rootPath ) : MINIMUM_FILE_SIZE; + } + + // IMount implementation + + @Override + public boolean exists( @Nonnull String path ) + { + if( !created() ) return path.isEmpty(); + + File file = getRealPath( path ); + return file.exists(); + } + + @Override + public boolean isDirectory( @Nonnull String path ) + { + if( !created() ) return path.isEmpty(); + + File file = getRealPath( path ); + return file.exists() && file.isDirectory(); + } + + @Override + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + if( !created() ) + { + if( !path.isEmpty() ) throw new FileOperationException( path, "Not a directory" ); + return; + } + + File file = getRealPath( path ); + if( !file.exists() || !file.isDirectory() ) throw new FileOperationException( path, "Not a directory" ); + + String[] paths = file.list(); + for( String subPath : paths ) + { + if( new File( file, subPath ).exists() ) contents.add( subPath ); + } + } + + @Override + public long getSize( @Nonnull String path ) throws IOException + { + if( !created() ) + { + if( path.isEmpty() ) return 0; + } + else + { + File file = getRealPath( path ); + if( file.exists() ) return file.isDirectory() ? 0 : file.length(); + } + + throw new FileOperationException( path, "No such file" ); + } + + @Nonnull + @Override + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + if( created() ) + { + File file = getRealPath( path ); + if( file.exists() && !file.isDirectory() ) return FileChannel.open( file.toPath(), READ_OPTIONS ); + } + + throw new FileOperationException( path, "No such file" ); + } + + @Nonnull + @Override + public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException + { + if( created() ) + { + File file = getRealPath( path ); + if( file.exists() ) return Files.readAttributes( file.toPath(), BasicFileAttributes.class ); + } + + throw new FileOperationException( path, "No such file" ); + } + + // IWritableMount implementation + + @Override + public void makeDirectory( @Nonnull String path ) throws IOException + { + create(); + File file = getRealPath( path ); + if( file.exists() ) + { + if( !file.isDirectory() ) throw new FileOperationException( path, "File exists" ); + return; + } + + int dirsToCreate = 1; + File parent = file.getParentFile(); + while( !parent.exists() ) + { + ++dirsToCreate; + parent = parent.getParentFile(); + } + + if( getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE ) + { + throw new FileOperationException( path, "Out of space" ); + } + + if( file.mkdirs() ) + { + usedSpace += dirsToCreate * MINIMUM_FILE_SIZE; + } + else + { + throw new FileOperationException( path, "Access denied" ); + } + } + + @Override + public void delete( @Nonnull String path ) throws IOException + { + if( path.isEmpty() ) throw new FileOperationException( path, "Access denied" ); + + if( created() ) + { + File file = getRealPath( path ); + if( file.exists() ) deleteRecursively( file ); + } + } + + private void deleteRecursively( File file ) throws IOException + { + // Empty directories first + if( file.isDirectory() ) + { + String[] children = file.list(); + for( String aChildren : children ) + { + deleteRecursively( new File( file, aChildren ) ); + } + } + + // Then delete + long fileSize = file.isDirectory() ? 0 : file.length(); + boolean success = file.delete(); + if( success ) + { + usedSpace -= Math.max( MINIMUM_FILE_SIZE, fileSize ); + } + else + { + throw new IOException( "Access denied" ); + } + } + + @Nonnull + @Override + public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException + { + create(); + File file = getRealPath( path ); + if( file.exists() && file.isDirectory() ) throw new FileOperationException( path, "Cannot write to directory" ); + + if( file.exists() ) + { + usedSpace -= Math.max( file.length(), MINIMUM_FILE_SIZE ); + } + else if( getRemainingSpace() < MINIMUM_FILE_SIZE ) + { + throw new FileOperationException( path, "Out of space" ); + } + usedSpace += MINIMUM_FILE_SIZE; + + return new SeekableCountingChannel( Files.newByteChannel( file.toPath(), WRITE_OPTIONS ), MINIMUM_FILE_SIZE ); + } + + @Nonnull + @Override + public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException + { + if( !created() ) + { + throw new FileOperationException( path, "No such file" ); + } + + File file = getRealPath( path ); + if( !file.exists() ) throw new FileOperationException( path, "No such file" ); + if( file.isDirectory() ) throw new FileOperationException( path, "Cannot write to directory" ); + + // Allowing seeking when appending is not recommended, so we use a separate channel. + return new WritableCountingChannel( + Files.newByteChannel( file.toPath(), APPEND_OPTIONS ), + Math.max( MINIMUM_FILE_SIZE - file.length(), 0 ) + ); + } + + @Override + public long getRemainingSpace() + { + return Math.max( capacity - usedSpace, 0 ); + } + + @Nonnull + @Override + public OptionalLong getCapacity() + { + return OptionalLong.of( capacity - MINIMUM_FILE_SIZE ); + } + + private File getRealPath( String path ) + { + return new File( rootPath, path ); } private boolean created() { - return this.m_rootPath.exists(); + return rootPath.exists(); + } + + private void create() throws IOException + { + if( !rootPath.exists() ) + { + boolean success = rootPath.mkdirs(); + if( !success ) + { + throw new IOException( "Access denied" ); + } + } + } + + private static class Visitor extends SimpleFileVisitor + { + long size; + + @Override + public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs ) + { + size += MINIMUM_FILE_SIZE; + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) + { + size += Math.max( attrs.size(), MINIMUM_FILE_SIZE ); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed( Path file, IOException exc ) + { + ComputerCraft.log.error( "Error computing file size for {}", file, exc ); + return FileVisitResult.CONTINUE; + } } private static long measureUsedSpace( File file ) { - if( !file.exists() ) - { - return 0; - } + if( !file.exists() ) return 0; try { @@ -66,410 +416,4 @@ public class FileMount implements IWritableMount return 0; } } - - // IMount implementation - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - if( !this.created() ) - { - if( !path.isEmpty() ) - { - throw new FileOperationException( path, "Not a directory" ); - } - return; - } - - File file = this.getRealPath( path ); - if( !file.exists() || !file.isDirectory() ) - { - throw new FileOperationException( path, "Not a directory" ); - } - - String[] paths = file.list(); - for( String subPath : paths ) - { - if( new File( file, subPath ).exists() ) - { - contents.add( subPath ); - } - } - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - if( this.created() ) - { - File file = this.getRealPath( path ); - if( file.exists() && !file.isDirectory() ) - { - return FileChannel.open( file.toPath(), READ_OPTIONS ); - } - } - - throw new FileOperationException( path, "No such file" ); - } - - @Nonnull - @Override - public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException - { - if( this.created() ) - { - File file = this.getRealPath( path ); - if( file.exists() ) - { - return Files.readAttributes( file.toPath(), BasicFileAttributes.class ); - } - } - - throw new FileOperationException( path, "No such file" ); - } - - @Override - public boolean exists( @Nonnull String path ) - { - if( !this.created() ) - { - return path.isEmpty(); - } - - File file = this.getRealPath( path ); - return file.exists(); - } - - @Override - public boolean isDirectory( @Nonnull String path ) - { - if( !this.created() ) - { - return path.isEmpty(); - } - - File file = this.getRealPath( path ); - return file.exists() && file.isDirectory(); - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - if( !this.created() ) - { - if( path.isEmpty() ) - { - return 0; - } - } - else - { - File file = this.getRealPath( path ); - if( file.exists() ) - { - return file.isDirectory() ? 0 : file.length(); - } - } - - throw new FileOperationException( path, "No such file" ); - } - - // IWritableMount implementation - - private File getRealPath( String path ) - { - return new File( this.m_rootPath, path ); - } - - @Override - public void makeDirectory( @Nonnull String path ) throws IOException - { - this.create(); - File file = this.getRealPath( path ); - if( file.exists() ) - { - if( !file.isDirectory() ) - { - throw new FileOperationException( path, "File exists" ); - } - return; - } - - int dirsToCreate = 1; - File parent = file.getParentFile(); - while( !parent.exists() ) - { - ++dirsToCreate; - parent = parent.getParentFile(); - } - - if( this.getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE ) - { - throw new FileOperationException( path, "Out of space" ); - } - - if( file.mkdirs() ) - { - this.m_usedSpace += dirsToCreate * MINIMUM_FILE_SIZE; - } - else - { - throw new FileOperationException( path, "Access denied" ); - } - } - - @Override - public void delete( @Nonnull String path ) throws IOException - { - if( path.isEmpty() ) - { - throw new FileOperationException( path, "Access denied" ); - } - - if( this.created() ) - { - File file = this.getRealPath( path ); - if( file.exists() ) - { - this.deleteRecursively( file ); - } - } - } - - @Nonnull - @Override - public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException - { - this.create(); - File file = this.getRealPath( path ); - if( file.exists() && file.isDirectory() ) - { - throw new FileOperationException( path, "Cannot write to directory" ); - } - - if( file.exists() ) - { - this.m_usedSpace -= Math.max( file.length(), MINIMUM_FILE_SIZE ); - } - else if( this.getRemainingSpace() < MINIMUM_FILE_SIZE ) - { - throw new FileOperationException( path, "Out of space" ); - } - this.m_usedSpace += MINIMUM_FILE_SIZE; - - return new SeekableCountingChannel( Files.newByteChannel( file.toPath(), WRITE_OPTIONS ), MINIMUM_FILE_SIZE ); - } - - @Nonnull - @Override - public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException - { - if( !this.created() ) - { - throw new FileOperationException( path, "No such file" ); - } - - File file = this.getRealPath( path ); - if( !file.exists() ) - { - throw new FileOperationException( path, "No such file" ); - } - if( file.isDirectory() ) - { - throw new FileOperationException( path, "Cannot write to directory" ); - } - - // Allowing seeking when appending is not recommended, so we use a separate channel. - return new WritableCountingChannel( Files.newByteChannel( file.toPath(), APPEND_OPTIONS ), Math.max( MINIMUM_FILE_SIZE - file.length(), 0 ) ); - } - - @Override - public long getRemainingSpace() - { - return Math.max( this.m_capacity - this.m_usedSpace, 0 ); - } - - @Nonnull - @Override - public OptionalLong getCapacity() - { - return OptionalLong.of( this.m_capacity - MINIMUM_FILE_SIZE ); - } - - private void create() throws IOException - { - if( !this.m_rootPath.exists() ) - { - boolean success = this.m_rootPath.mkdirs(); - if( !success ) - { - throw new IOException( "Access denied" ); - } - } - } - - private void deleteRecursively( File file ) throws IOException - { - // Empty directories first - if( file.isDirectory() ) - { - String[] children = file.list(); - for( String aChildren : children ) - { - this.deleteRecursively( new File( file, aChildren ) ); - } - } - - // Then delete - long fileSize = file.isDirectory() ? 0 : file.length(); - boolean success = file.delete(); - if( success ) - { - this.m_usedSpace -= Math.max( MINIMUM_FILE_SIZE, fileSize ); - } - else - { - throw new IOException( "Access denied" ); - } - } - - private static class Visitor extends SimpleFileVisitor - { - long size; - - @Override - public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs ) - { - this.size += MINIMUM_FILE_SIZE; - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) - { - this.size += Math.max( attrs.size(), MINIMUM_FILE_SIZE ); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed( Path file, IOException exc ) - { - ComputerCraft.log.error( "Error computing file size for {}", file, exc ); - return FileVisitResult.CONTINUE; - } - } - - private class WritableCountingChannel implements WritableByteChannel - { - - private final WritableByteChannel m_inner; - long m_ignoredBytesLeft; - - WritableCountingChannel( WritableByteChannel inner, long bytesToIgnore ) - { - this.m_inner = inner; - this.m_ignoredBytesLeft = bytesToIgnore; - } - - @Override - public int write( @Nonnull ByteBuffer b ) throws IOException - { - this.count( b.remaining() ); - return this.m_inner.write( b ); - } - - void count( long n ) throws IOException - { - this.m_ignoredBytesLeft -= n; - if( this.m_ignoredBytesLeft < 0 ) - { - long newBytes = -this.m_ignoredBytesLeft; - this.m_ignoredBytesLeft = 0; - - long bytesLeft = FileMount.this.m_capacity - FileMount.this.m_usedSpace; - if( newBytes > bytesLeft ) - { - throw new IOException( "Out of space" ); - } - FileMount.this.m_usedSpace += newBytes; - } - } - - @Override - public boolean isOpen() - { - return this.m_inner.isOpen(); - } - - @Override - public void close() throws IOException - { - this.m_inner.close(); - } - } - - private class SeekableCountingChannel extends WritableCountingChannel implements SeekableByteChannel - { - private final SeekableByteChannel m_inner; - - SeekableCountingChannel( SeekableByteChannel inner, long bytesToIgnore ) - { - super( inner, bytesToIgnore ); - this.m_inner = inner; - } - - @Override - public int read( ByteBuffer dst ) throws ClosedChannelException - { - if( !this.m_inner.isOpen() ) - { - throw new ClosedChannelException(); - } - throw new NonReadableChannelException(); - } - - @Override - public long position() throws IOException - { - return this.m_inner.position(); - } - - @Override - public SeekableByteChannel position( long newPosition ) throws IOException - { - if( !this.isOpen() ) - { - throw new ClosedChannelException(); - } - if( newPosition < 0 ) - { - throw new IllegalArgumentException( "Cannot seek before the beginning of the stream" ); - } - - long delta = newPosition - this.m_inner.position(); - if( delta < 0 ) - { - this.m_ignoredBytesLeft -= delta; - } - else - { - this.count( delta ); - } - - return this.m_inner.position( newPosition ); - } - - @Override - public long size() throws IOException - { - return this.m_inner.size(); - } - - @Override - public SeekableByteChannel truncate( long size ) throws IOException - { - throw new IOException( "Not yet implemented" ); - } - } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java b/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java index 8756e0ea8..482d0d080 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java +++ b/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; public class FileSystemException extends Exception diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java b/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java index dfa3324af..e0082dcbe 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import dan200.computercraft.api.filesystem.IFileSystem; @@ -18,11 +17,11 @@ import java.util.function.Function; public class FileSystemWrapperMount implements IFileSystem { - private final FileSystem m_filesystem; + private final FileSystem filesystem; public FileSystemWrapperMount( FileSystem filesystem ) { - this.m_filesystem = filesystem; + this.filesystem = filesystem; } @Override @@ -30,7 +29,7 @@ public class FileSystemWrapperMount implements IFileSystem { try { - this.m_filesystem.makeDir( path ); + filesystem.makeDir( path ); } catch( FileSystemException e ) { @@ -43,63 +42,7 @@ public class FileSystemWrapperMount implements IFileSystem { try { - this.m_filesystem.delete( path ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Nonnull - @Override - public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException - { - try - { - return this.m_filesystem.openForWrite( path, false, Function.identity() ) - .get(); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Nonnull - @Override - public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException - { - try - { - return this.m_filesystem.openForWrite( path, true, Function.identity() ) - .get(); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public long getRemainingSpace() throws IOException - { - try - { - return this.m_filesystem.getFreeSpace( "/" ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - try - { - Collections.addAll( contents, this.m_filesystem.list( path ) ); + filesystem.delete( path ); } catch( FileSystemException e ) { @@ -114,8 +57,48 @@ public class FileSystemWrapperMount implements IFileSystem try { // FIXME: Think of a better way of implementing this, so closing this will close on the computer. - return this.m_filesystem.openForRead( path, Function.identity() ) - .get(); + return filesystem.openForRead( path, Function.identity() ).get(); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); + } + } + + @Nonnull + @Override + public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException + { + try + { + return filesystem.openForWrite( path, false, Function.identity() ).get(); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); + } + } + + @Nonnull + @Override + public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException + { + try + { + return filesystem.openForWrite( path, true, Function.identity() ).get(); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); + } + } + + @Override + public long getRemainingSpace() throws IOException + { + try + { + return filesystem.getFreeSpace( "/" ); } catch( FileSystemException e ) { @@ -128,7 +111,7 @@ public class FileSystemWrapperMount implements IFileSystem { try { - return this.m_filesystem.exists( path ); + return filesystem.exists( path ); } catch( FileSystemException e ) { @@ -141,7 +124,20 @@ public class FileSystemWrapperMount implements IFileSystem { try { - return this.m_filesystem.isDir( path ); + return filesystem.isDir( path ); + } + catch( FileSystemException e ) + { + throw new IOException( e.getMessage() ); + } + } + + @Override + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + try + { + Collections.addAll( contents, filesystem.list( path ) ); } catch( FileSystemException e ) { @@ -154,7 +150,7 @@ public class FileSystemWrapperMount implements IFileSystem { try { - return this.m_filesystem.getSize( path ); + return filesystem.getSize( path ); } catch( FileSystemException e ) { @@ -165,7 +161,7 @@ public class FileSystemWrapperMount implements IFileSystem @Override public String combine( String path, String child ) { - return this.m_filesystem.combine( path, child ); + return filesystem.combine( path, child ); } @Override @@ -173,7 +169,7 @@ public class FileSystemWrapperMount implements IFileSystem { try { - this.m_filesystem.copy( from, to ); + filesystem.copy( from, to ); } catch( FileSystemException e ) { @@ -186,7 +182,7 @@ public class FileSystemWrapperMount implements IFileSystem { try { - this.m_filesystem.move( from, to ); + filesystem.move( from, to ); } catch( FileSystemException e ) { diff --git a/src/main/java/dan200/computercraft/core/filesystem/JarMount.java b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java index e22a7bf9b..f902261a0 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/JarMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import com.google.common.cache.Cache; @@ -48,18 +47,20 @@ public class JarMount implements IMount private static final int MAX_CACHE_SIZE = 64 << 20; /** - * We maintain a cache of the contents of all files in the mount. This allows us to allow seeking within ROM files, and reduces the amount we need to - * access disk for computer startup. + * We maintain a cache of the contents of all files in the mount. This allows us to allow + * seeking within ROM files, and reduces the amount we need to access disk for computer startup. */ private static final Cache CONTENTS_CACHE = CacheBuilder.newBuilder() .concurrencyLevel( 4 ) .expireAfterAccess( 60, TimeUnit.SECONDS ) .maximumWeight( MAX_CACHE_SIZE ) - .weakKeys().weigher( ( k, v ) -> v.length ).build(); + .weakKeys() + .weigher( ( k, v ) -> v.length ) + .build(); /** - * We have a {@link ReferenceQueue} of all mounts, a long with their corresponding {@link ZipFile}. If the mount has been destroyed, we clean up after - * it. + * We have a {@link ReferenceQueue} of all mounts, a long with their corresponding {@link ZipFile}. If + * the mount has been destroyed, we clean up after it. */ private static final ReferenceQueue MOUNT_QUEUE = new ReferenceQueue<>(); @@ -71,15 +72,12 @@ public class JarMount implements IMount // Cleanup any old mounts. It's unlikely that there will be any, but it's best to be safe. cleanup(); - if( !jarFile.exists() || jarFile.isDirectory() ) - { - throw new FileNotFoundException( "Cannot find " + jarFile ); - } + if( !jarFile.exists() || jarFile.isDirectory() ) throw new FileNotFoundException( "Cannot find " + jarFile ); // Open the zip file try { - this.zip = new ZipFile( jarFile ); + zip = new ZipFile( jarFile ); } catch( IOException e ) { @@ -87,9 +85,9 @@ public class JarMount implements IMount } // Ensure the root entry exists. - if( this.zip.getEntry( subPath ) == null ) + if( zip.getEntry( subPath ) == null ) { - this.zip.close(); + zip.close(); throw new FileNotFoundException( "Zip does not contain path" ); } @@ -97,50 +95,49 @@ public class JarMount implements IMount new MountReference( this ); // Read in all the entries - this.root = new FileEntry(); - Enumeration zipEntries = this.zip.entries(); + root = new FileEntry(); + Enumeration zipEntries = zip.entries(); while( zipEntries.hasMoreElements() ) { ZipEntry entry = zipEntries.nextElement(); String entryPath = entry.getName(); - if( !entryPath.startsWith( subPath ) ) - { - continue; - } + if( !entryPath.startsWith( subPath ) ) continue; String localPath = FileSystem.toLocal( entryPath, subPath ); - this.create( entry, localPath ); + create( entry, localPath ); } } - private static void cleanup() + private FileEntry get( String path ) { - Reference next; - while( (next = MOUNT_QUEUE.poll()) != null ) + FileEntry lastEntry = root; + int lastIndex = 0; + + while( lastEntry != null && lastIndex < path.length() ) { - IoUtil.closeQuietly( ((MountReference) next).file ); + int nextIndex = path.indexOf( '/', lastIndex ); + if( nextIndex < 0 ) nextIndex = path.length(); + + lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); + lastIndex = nextIndex + 1; } + + return lastEntry; } private void create( ZipEntry entry, String localPath ) { - FileEntry lastEntry = this.root; + FileEntry lastEntry = root; int lastIndex = 0; while( lastIndex < localPath.length() ) { int nextIndex = localPath.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) - { - nextIndex = localPath.length(); - } + if( nextIndex < 0 ) nextIndex = localPath.length(); String part = localPath.substring( lastIndex, nextIndex ); - if( lastEntry.children == null ) - { - lastEntry.children = new HashMap<>( 0 ); - } + if( lastEntry.children == null ) lastEntry.children = new HashMap<>( 0 ); FileEntry nextEntry = lastEntry.children.get( part ); if( nextEntry == null || !nextEntry.isDirectory() ) @@ -155,42 +152,54 @@ public class JarMount implements IMount lastEntry.setup( entry ); } + @Override + public boolean exists( @Nonnull String path ) + { + return get( path ) != null; + } + + @Override + public boolean isDirectory( @Nonnull String path ) + { + FileEntry file = get( path ); + return file != null && file.isDirectory(); + } + @Override public void list( @Nonnull String path, @Nonnull List contents ) throws IOException { - FileEntry file = this.get( path ); - if( file == null || !file.isDirectory() ) - { - throw new FileOperationException( path, "Not a directory" ); - } + FileEntry file = get( path ); + if( file == null || !file.isDirectory() ) throw new FileOperationException( path, "Not a directory" ); file.list( contents ); } + @Override + public long getSize( @Nonnull String path ) throws IOException + { + FileEntry file = get( path ); + if( file != null ) return file.size; + throw new FileOperationException( path, "No such file" ); + } + @Nonnull @Override public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException { - FileEntry file = this.get( path ); + FileEntry file = get( path ); if( file != null && !file.isDirectory() ) { byte[] contents = CONTENTS_CACHE.getIfPresent( file ); - if( contents != null ) - { - return new ArrayByteChannel( contents ); - } + if( contents != null ) return new ArrayByteChannel( contents ); try { - ZipEntry entry = this.zip.getEntry( file.path ); + ZipEntry entry = zip.getEntry( file.path ); if( entry != null ) { - try( InputStream stream = this.zip.getInputStream( entry ) ) + try( InputStream stream = zip.getInputStream( entry ) ) { - if( stream.available() > MAX_CACHED_SIZE ) - { - return Channels.newChannel( stream ); - } + if( stream.available() > MAX_CACHED_SIZE ) return Channels.newChannel( stream ); contents = ByteStreams.toByteArray( stream ); CONTENTS_CACHE.put( file, contents ); @@ -211,63 +220,16 @@ public class JarMount implements IMount @Override public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException { - FileEntry file = this.get( path ); + FileEntry file = get( path ); if( file != null ) { - ZipEntry entry = this.zip.getEntry( file.path ); - if( entry != null ) - { - return new ZipEntryAttributes( entry ); - } + ZipEntry entry = zip.getEntry( file.path ); + if( entry != null ) return new ZipEntryAttributes( entry ); } throw new FileOperationException( path, "No such file" ); } - @Override - public boolean exists( @Nonnull String path ) - { - return this.get( path ) != null; - } - - private FileEntry get( String path ) - { - FileEntry lastEntry = this.root; - int lastIndex = 0; - - while( lastEntry != null && lastIndex < path.length() ) - { - int nextIndex = path.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) - { - nextIndex = path.length(); - } - - lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); - lastIndex = nextIndex + 1; - } - - return lastEntry; - } - - @Override - public boolean isDirectory( @Nonnull String path ) - { - FileEntry file = this.get( path ); - return file != null && file.isDirectory(); - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - FileEntry file = this.get( path ); - if( file != null ) - { - return file.size; - } - throw new FileOperationException( path, "No such file" ); - } - private static class FileEntry { String path; @@ -276,25 +238,19 @@ public class JarMount implements IMount void setup( ZipEntry entry ) { - this.path = entry.getName(); - this.size = entry.getSize(); - if( this.children == null && entry.isDirectory() ) - { - this.children = new HashMap<>( 0 ); - } + path = entry.getName(); + size = entry.getSize(); + if( children == null && entry.isDirectory() ) children = new HashMap<>( 0 ); } boolean isDirectory() { - return this.children != null; + return children != null; } void list( List contents ) { - if( this.children != null ) - { - contents.addAll( this.children.keySet() ); - } + if( children != null ) contents.addAll( children.keySet() ); } } @@ -309,9 +265,14 @@ public class JarMount implements IMount } } + private static void cleanup() + { + Reference next; + while( (next = MOUNT_QUEUE.poll()) != null ) IoUtil.closeQuietly( ((MountReference) next).file ); + } + private static class ZipEntryAttributes implements BasicFileAttributes { - private static final FileTime EPOCH = FileTime.from( Instant.EPOCH ); private final ZipEntry entry; ZipEntryAttributes( ZipEntry entry ) @@ -322,32 +283,32 @@ public class JarMount implements IMount @Override public FileTime lastModifiedTime() { - return orEpoch( this.entry.getLastModifiedTime() ); + return orEpoch( entry.getLastModifiedTime() ); } @Override public FileTime lastAccessTime() { - return orEpoch( this.entry.getLastAccessTime() ); + return orEpoch( entry.getLastAccessTime() ); } @Override public FileTime creationTime() { - FileTime time = this.entry.getCreationTime(); - return time == null ? this.lastModifiedTime() : time; + FileTime time = entry.getCreationTime(); + return time == null ? lastModifiedTime() : time; } @Override public boolean isRegularFile() { - return !this.entry.isDirectory(); + return !entry.isDirectory(); } @Override public boolean isDirectory() { - return this.entry.isDirectory(); + return entry.isDirectory(); } @Override @@ -365,7 +326,7 @@ public class JarMount implements IMount @Override public long size() { - return this.entry.getSize(); + return entry.getSize(); } @Override @@ -374,6 +335,7 @@ public class JarMount implements IMount return null; } + private static final FileTime EPOCH = FileTime.from( Instant.EPOCH ); private static FileTime orEpoch( FileTime time ) { diff --git a/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java b/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java index 5800a421b..96b11f24f 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java +++ b/src/main/java/dan200/computercraft/core/filesystem/MountWrapper.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import dan200.computercraft.api.filesystem.FileOperationException; @@ -33,7 +32,7 @@ class MountWrapper this.label = label; this.location = location; this.mount = mount; - this.writableMount = null; + writableMount = null; } MountWrapper( String label, String location, IWritableMount mount ) @@ -41,29 +40,26 @@ class MountWrapper this.label = label; this.location = location; this.mount = mount; - this.writableMount = mount; + writableMount = mount; } public String getLabel() { - return this.label; + return label; } public String getLocation() { - return this.location; + return location; } public long getFreeSpace() { - if( this.writableMount == null ) - { - return 0; - } + if( writableMount == null ) return 0; try { - return this.writableMount.getRemainingSpace(); + return writableMount.getRemainingSpace(); } catch( IOException e ) { @@ -73,50 +69,242 @@ class MountWrapper public OptionalLong getCapacity() { - return this.writableMount == null ? OptionalLong.empty() : this.writableMount.getCapacity(); + return writableMount == null ? OptionalLong.empty() : writableMount.getCapacity(); } public boolean isReadOnly( String path ) { - return this.writableMount == null; + return writableMount == null; } public boolean exists( String path ) throws FileSystemException { - path = this.toLocal( path ); + path = toLocal( path ); try { - return this.mount.exists( path ); + return mount.exists( path ); } catch( IOException e ) { - throw this.localExceptionOf( path, e ); + throw localExceptionOf( path, e ); + } + } + + public boolean isDirectory( String path ) throws FileSystemException + { + path = toLocal( path ); + try + { + return mount.exists( path ) && mount.isDirectory( path ); + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + public void list( String path, List contents ) throws FileSystemException + { + path = toLocal( path ); + try + { + if( !mount.exists( path ) || !mount.isDirectory( path ) ) + { + throw localExceptionOf( path, "Not a directory" ); + } + + mount.list( path, contents ); + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + public long getSize( String path ) throws FileSystemException + { + path = toLocal( path ); + try + { + if( !mount.exists( path ) ) throw localExceptionOf( path, "No such file" ); + return mount.isDirectory( path ) ? 0 : mount.getSize( path ); + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + @Nonnull + public BasicFileAttributes getAttributes( String path ) throws FileSystemException + { + path = toLocal( path ); + try + { + if( !mount.exists( path ) ) throw localExceptionOf( path, "No such file" ); + return mount.getAttributes( path ); + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + public ReadableByteChannel openForRead( String path ) throws FileSystemException + { + path = toLocal( path ); + try + { + if( mount.exists( path ) && !mount.isDirectory( path ) ) + { + return mount.openForRead( path ); + } + else + { + throw localExceptionOf( path, "No such file" ); + } + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + public void makeDirectory( String path ) throws FileSystemException + { + if( writableMount == null ) throw exceptionOf( path, "Access denied" ); + + path = toLocal( path ); + try + { + if( mount.exists( path ) ) + { + if( !mount.isDirectory( path ) ) throw localExceptionOf( path, "File exists" ); + } + else + { + writableMount.makeDirectory( path ); + } + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + public void delete( String path ) throws FileSystemException + { + if( writableMount == null ) throw exceptionOf( path, "Access denied" ); + + path = toLocal( path ); + try + { + if( mount.exists( path ) ) + { + writableMount.delete( path ); + } + } + catch( AccessDeniedException e ) + { + throw new FileSystemException( "Access denied" ); + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + public WritableByteChannel openForWrite( String path ) throws FileSystemException + { + if( writableMount == null ) throw exceptionOf( path, "Access denied" ); + + path = toLocal( path ); + try + { + if( mount.exists( path ) && mount.isDirectory( path ) ) + { + throw localExceptionOf( path, "Cannot write to directory" ); + } + else + { + if( !path.isEmpty() ) + { + String dir = FileSystem.getDirectory( path ); + if( !dir.isEmpty() && !mount.exists( path ) ) + { + writableMount.makeDirectory( dir ); + } + } + return writableMount.openForWrite( path ); + } + } + catch( AccessDeniedException e ) + { + throw new FileSystemException( "Access denied" ); + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); + } + } + + public WritableByteChannel openForAppend( String path ) throws FileSystemException + { + if( writableMount == null ) throw exceptionOf( path, "Access denied" ); + + path = toLocal( path ); + try + { + if( !mount.exists( path ) ) + { + if( !path.isEmpty() ) + { + String dir = FileSystem.getDirectory( path ); + if( !dir.isEmpty() && !mount.exists( path ) ) + { + writableMount.makeDirectory( dir ); + } + } + return writableMount.openForWrite( path ); + } + else if( mount.isDirectory( path ) ) + { + throw localExceptionOf( path, "Cannot write to directory" ); + } + else + { + return writableMount.openForAppend( path ); + } + } + catch( AccessDeniedException e ) + { + throw new FileSystemException( "Access denied" ); + } + catch( IOException e ) + { + throw localExceptionOf( path, e ); } } private String toLocal( String path ) { - return FileSystem.toLocal( path, this.location ); + return FileSystem.toLocal( path, location ); } private FileSystemException localExceptionOf( @Nullable String localPath, @Nonnull IOException e ) { - if( !this.location.isEmpty() && e instanceof FileOperationException ) + if( !location.isEmpty() && e instanceof FileOperationException ) { FileOperationException ex = (FileOperationException) e; - if( ex.getFilename() != null ) - { - return this.localExceptionOf( ex.getFilename(), ex.getMessage() ); - } + if( ex.getFilename() != null ) return localExceptionOf( ex.getFilename(), ex.getMessage() ); } if( e instanceof java.nio.file.FileSystemException ) { // This error will contain the absolute path, leaking information about where MC is installed. We drop that, // just taking the reason. We assume that the error refers to the input path. - String message = ((java.nio.file.FileSystemException) e).getReason() - .trim(); - return localPath == null ? new FileSystemException( message ) : this.localExceptionOf( localPath, message ); + String message = ((java.nio.file.FileSystemException) e).getReason().trim(); + return localPath == null ? new FileSystemException( message ) : localExceptionOf( localPath, message ); } return new FileSystemException( e.getMessage() ); @@ -124,10 +312,7 @@ class MountWrapper private FileSystemException localExceptionOf( String path, String message ) { - if( !this.location.isEmpty() ) - { - path = path.isEmpty() ? this.location : this.location + "/" + path; - } + if( !location.isEmpty() ) path = path.isEmpty() ? location : location + "/" + path; return exceptionOf( path, message ); } @@ -135,221 +320,4 @@ class MountWrapper { return new FileSystemException( "/" + path + ": " + message ); } - - public boolean isDirectory( String path ) throws FileSystemException - { - path = this.toLocal( path ); - try - { - return this.mount.exists( path ) && this.mount.isDirectory( path ); - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - public void list( String path, List contents ) throws FileSystemException - { - path = this.toLocal( path ); - try - { - if( !this.mount.exists( path ) || !this.mount.isDirectory( path ) ) - { - throw this.localExceptionOf( path, "Not a directory" ); - } - - this.mount.list( path, contents ); - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - public long getSize( String path ) throws FileSystemException - { - path = this.toLocal( path ); - try - { - if( !this.mount.exists( path ) ) - { - throw this.localExceptionOf( path, "No such file" ); - } - return this.mount.isDirectory( path ) ? 0 : this.mount.getSize( path ); - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - @Nonnull - public BasicFileAttributes getAttributes( String path ) throws FileSystemException - { - path = this.toLocal( path ); - try - { - if( !this.mount.exists( path ) ) - { - throw this.localExceptionOf( path, "No such file" ); - } - return this.mount.getAttributes( path ); - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - public ReadableByteChannel openForRead( String path ) throws FileSystemException - { - path = this.toLocal( path ); - try - { - if( this.mount.exists( path ) && !this.mount.isDirectory( path ) ) - { - return this.mount.openForRead( path ); - } - else - { - throw this.localExceptionOf( path, "No such file" ); - } - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - public void makeDirectory( String path ) throws FileSystemException - { - if( this.writableMount == null ) - { - throw exceptionOf( path, "Access denied" ); - } - - path = this.toLocal( path ); - try - { - if( this.mount.exists( path ) ) - { - if( !this.mount.isDirectory( path ) ) - { - throw this.localExceptionOf( path, "File exists" ); - } - } - else - { - this.writableMount.makeDirectory( path ); - } - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - public void delete( String path ) throws FileSystemException - { - if( this.writableMount == null ) - { - throw exceptionOf( path, "Access denied" ); - } - - path = this.toLocal( path ); - try - { - if( this.mount.exists( path ) ) - { - this.writableMount.delete( path ); - } - } - catch( AccessDeniedException e ) - { - throw new FileSystemException( "Access denied" ); - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - public WritableByteChannel openForWrite( String path ) throws FileSystemException - { - if( this.writableMount == null ) - { - throw exceptionOf( path, "Access denied" ); - } - - path = this.toLocal( path ); - try - { - if( this.mount.exists( path ) && this.mount.isDirectory( path ) ) - { - throw this.localExceptionOf( path, "Cannot write to directory" ); - } - else - { - if( !path.isEmpty() ) - { - String dir = FileSystem.getDirectory( path ); - if( !dir.isEmpty() && !this.mount.exists( path ) ) - { - this.writableMount.makeDirectory( dir ); - } - } - return this.writableMount.openForWrite( path ); - } - } - catch( AccessDeniedException e ) - { - throw new FileSystemException( "Access denied" ); - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } - - public WritableByteChannel openForAppend( String path ) throws FileSystemException - { - if( this.writableMount == null ) - { - throw exceptionOf( path, "Access denied" ); - } - - path = this.toLocal( path ); - try - { - if( !this.mount.exists( path ) ) - { - if( !path.isEmpty() ) - { - String dir = FileSystem.getDirectory( path ); - if( !dir.isEmpty() && !this.mount.exists( path ) ) - { - this.writableMount.makeDirectory( dir ); - } - } - return this.writableMount.openForWrite( path ); - } - else if( this.mount.isDirectory( path ) ) - { - throw this.localExceptionOf( path, "Cannot write to directory" ); - } - else - { - return this.writableMount.openForAppend( path ); - } - } - catch( AccessDeniedException e ) - { - throw new FileSystemException( "Access denied" ); - } - catch( IOException e ) - { - throw this.localExceptionOf( path, e ); - } - } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java index d60dd8ff2..0131e33b2 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import com.google.common.cache.Cache; @@ -49,17 +48,18 @@ public final class ResourceMount implements IMount private static final byte[] TEMP_BUFFER = new byte[8192]; /** - * We maintain a cache of the contents of all files in the mount. This allows us to allow seeking within ROM files, and reduces the amount we need to - * access disk for computer startup. + * We maintain a cache of the contents of all files in the mount. This allows us to allow + * seeking within ROM files, and reduces the amount we need to access disk for computer startup. */ private static final Cache CONTENTS_CACHE = CacheBuilder.newBuilder() .concurrencyLevel( 4 ) .expireAfterAccess( 60, TimeUnit.SECONDS ) .maximumWeight( MAX_CACHE_SIZE ) - .weakKeys().weigher( ( k, v ) -> v.length ).build(); + .weakKeys() + .weigher( ( k, v ) -> v.length ) + .build(); - private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues() - .concurrencyLevel( 1 ); + private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues().concurrencyLevel( 1 ); /** * Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes. @@ -73,6 +73,25 @@ public final class ResourceMount implements IMount @Nullable private FileEntry root; + public static ResourceMount get( String namespace, String subPath, ReloadableResourceManager manager ) + { + Map cache; + + synchronized( MOUNT_CACHE ) + { + cache = MOUNT_CACHE.get( manager ); + if( cache == null ) MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() ); + } + + Identifier path = new Identifier( namespace, subPath ); + synchronized( cache ) + { + ResourceMount mount = cache.get( path ); + if( mount == null ) cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) ); + return mount; + } + } + private ResourceMount( String namespace, String subPath, ReloadableResourceManager manager ) { this.namespace = namespace; @@ -80,10 +99,7 @@ public final class ResourceMount implements IMount this.manager = manager; Listener.INSTANCE.add( manager, this ); - if( this.root == null ) - { - this.load(); - } + if( root == null ) load(); } private void load() @@ -98,8 +114,8 @@ public final class ResourceMount implements IMount if( !file.getNamespace().equals( namespace ) ) continue; - String localPath = FileSystem.toLocal( file.getPath(), this.subPath ); - this.create( newRoot, localPath ); + String localPath = FileSystem.toLocal( file.getPath(), subPath ); + create( newRoot, localPath ); hasAny = true; } @@ -115,22 +131,33 @@ public final class ResourceMount implements IMount } } + private FileEntry get( String path ) + { + FileEntry lastEntry = root; + int lastIndex = 0; + + while( lastEntry != null && lastIndex < path.length() ) + { + int nextIndex = path.indexOf( '/', lastIndex ); + if( nextIndex < 0 ) nextIndex = path.length(); + + lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); + lastIndex = nextIndex + 1; + } + + return lastEntry; + } + private void create( FileEntry lastEntry, String path ) { int lastIndex = 0; while( lastIndex < path.length() ) { int nextIndex = path.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) - { - nextIndex = path.length(); - } + if( nextIndex < 0 ) nextIndex = path.length(); String part = path.substring( lastIndex, nextIndex ); - if( lastEntry.children == null ) - { - lastEntry.children = new HashMap<>(); - } + if( lastEntry.children == null ) lastEntry.children = new HashMap<>(); FileEntry nextEntry = lastEntry.children.get( part ); if( nextEntry == null ) @@ -138,7 +165,7 @@ public final class ResourceMount implements IMount Identifier childPath; try { - childPath = new Identifier( this.namespace, this.subPath + "/" + path ); + childPath = new Identifier( namespace, subPath + "/" + path ); } catch( InvalidIdentifierException e ) { @@ -153,137 +180,43 @@ public final class ResourceMount implements IMount } } - public static ResourceMount get( String namespace, String subPath, ReloadableResourceManager manager ) - { - Map cache; - - synchronized( MOUNT_CACHE ) - { - cache = MOUNT_CACHE.get( manager ); - if( cache == null ) - { - MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() ); - } - } - - Identifier path = new Identifier( namespace, subPath ); - synchronized( cache ) - { - ResourceMount mount = cache.get( path ); - if( mount == null ) - { - cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) ); - } - return mount; - } - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - FileEntry file = this.get( path ); - if( file == null || !file.isDirectory() ) - { - throw new IOException( "/" + path + ": Not a directory" ); - } - - file.list( contents ); - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - FileEntry file = this.get( path ); - if( file != null && !file.isDirectory() ) - { - byte[] contents = CONTENTS_CACHE.getIfPresent( file ); - if( contents != null ) - { - return new ArrayByteChannel( contents ); - } - - try - { - InputStream stream = manager.getResource( file.identifier ).getInputStream(); - if( stream.available() > MAX_CACHED_SIZE ) return Channels.newChannel( stream ); - - try - { - contents = ByteStreams.toByteArray( stream ); - } - finally - { - IoUtil.closeQuietly( stream ); - } - CONTENTS_CACHE.put( file, contents ); - return new ArrayByteChannel( contents ); - } - catch( FileNotFoundException ignored ) - { - } - } - - throw new IOException( "/" + path + ": No such file" ); - } - @Override public boolean exists( @Nonnull String path ) { - return this.get( path ) != null; - } - - private FileEntry get( String path ) - { - FileEntry lastEntry = this.root; - int lastIndex = 0; - - while( lastEntry != null && lastIndex < path.length() ) - { - int nextIndex = path.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) - { - nextIndex = path.length(); - } - - lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); - lastIndex = nextIndex + 1; - } - - return lastEntry; + return get( path ) != null; } @Override public boolean isDirectory( @Nonnull String path ) { - FileEntry file = this.get( path ); + FileEntry file = get( path ); return file != null && file.isDirectory(); } + @Override + public void list( @Nonnull String path, @Nonnull List contents ) throws IOException + { + FileEntry file = get( path ); + if( file == null || !file.isDirectory() ) throw new IOException( "/" + path + ": Not a directory" ); + + file.list( contents ); + } + @Override public long getSize( @Nonnull String path ) throws IOException { - FileEntry file = this.get( path ); + FileEntry file = get( path ); if( file != null ) { - if( file.size != -1 ) - { - return file.size; - } - if( file.isDirectory() ) - { - return file.size = 0; - } + if( file.size != -1 ) return file.size; + if( file.isDirectory() ) return file.size = 0; byte[] contents = CONTENTS_CACHE.getIfPresent( file ); - if( contents != null ) - { - return file.size = contents.length; - } + if( contents != null ) return file.size = contents.length; try { - Resource resource = this.manager.getResource( file.identifier ); + Resource resource = manager.getResource( file.identifier ); InputStream s = resource.getInputStream(); int total = 0, read = 0; do @@ -303,6 +236,41 @@ public final class ResourceMount implements IMount throw new IOException( "/" + path + ": No such file" ); } + @Nonnull + @Override + public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException + { + FileEntry file = get( path ); + if( file != null && !file.isDirectory() ) + { + byte[] contents = CONTENTS_CACHE.getIfPresent( file ); + if( contents != null ) return new ArrayByteChannel( contents ); + + try + { + InputStream stream = manager.getResource( file.identifier ).getInputStream(); + if( stream.available() > MAX_CACHED_SIZE ) return Channels.newChannel( stream ); + + try + { + contents = ByteStreams.toByteArray( stream ); + } + finally + { + IoUtil.closeQuietly( stream ); + } + + CONTENTS_CACHE.put( file, contents ); + return new ArrayByteChannel( contents ); + } + catch( FileNotFoundException ignored ) + { + } + } + + throw new IOException( "/" + path + ": No such file" ); + } + private static class FileEntry { final Identifier identifier; @@ -316,21 +284,20 @@ public final class ResourceMount implements IMount boolean isDirectory() { - return this.children != null; + return children != null; } void list( List contents ) { - if( this.children != null ) - { - contents.addAll( this.children.keySet() ); - } + if( children != null ) contents.addAll( children.keySet() ); } } /** - * While people should really be keeping a permanent reference to this, some people construct it every method call, so let's make this as small as - * possible. + * A {@link ResourceReloadListener} which reloads any associated mounts. + * + * While people should really be keeping a permanent reference to this, some people construct it every + * method call, so let's make this as small as possible. */ static class Listener implements ResourceReloadListener { @@ -340,32 +307,25 @@ public final class ResourceMount implements IMount private final Set managers = Collections.newSetFromMap( new WeakHashMap<>() ); @Override - public CompletableFuture reload( Synchronizer synchronizer, ResourceManager resourceManager, Profiler profiler, Profiler profiler1, - Executor executor, Executor executor1 ) + public CompletableFuture reload( Synchronizer synchronizer, ResourceManager manager, Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, Executor applyExecutor ) { return CompletableFuture.runAsync( () -> { - profiler.push( "Mount reloading" ); + prepareProfiler.push( "Mount reloading" ); try { - for( ResourceMount mount : this.mounts ) - { - mount.load(); - } + for( ResourceMount mount : this.mounts ) mount.load(); } finally { - profiler.pop(); + prepareProfiler.pop(); } - }, executor ); + }, prepareExecutor ); } synchronized void add( ReloadableResourceManager manager, ResourceMount mount ) { - if( this.managers.add( manager ) ) - { - manager.registerListener( this ); - } - this.mounts.add( mount ); + if( managers.add( manager ) ) manager.registerListener( this ); + mounts.add( mount ); } } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/SubMount.java b/src/main/java/dan200/computercraft/core/filesystem/SubMount.java index 1eb05f841..b596896c8 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/SubMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/SubMount.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import dan200.computercraft.api.filesystem.IMount; @@ -16,8 +15,8 @@ import java.util.List; public class SubMount implements IMount { - private IMount parent; - private String subPath; + private final IMount parent; + private final String subPath; public SubMount( IMount parent, String subPath ) { @@ -25,46 +24,46 @@ public class SubMount implements IMount this.subPath = subPath; } + @Override + public boolean exists( @Nonnull String path ) throws IOException + { + return parent.exists( getFullPath( path ) ); + } + + @Override + public boolean isDirectory( @Nonnull String path ) throws IOException + { + return parent.isDirectory( getFullPath( path ) ); + } + @Override public void list( @Nonnull String path, @Nonnull List contents ) throws IOException { - this.parent.list( this.getFullPath( path ), contents ); + parent.list( getFullPath( path ), contents ); + } + + @Override + public long getSize( @Nonnull String path ) throws IOException + { + return parent.getSize( getFullPath( path ) ); } @Nonnull @Override public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException { - return this.parent.openForRead( this.getFullPath( path ) ); + return parent.openForRead( getFullPath( path ) ); } @Nonnull @Override public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException { - return this.parent.getAttributes( this.getFullPath( path ) ); - } - - @Override - public boolean exists( @Nonnull String path ) throws IOException - { - return this.parent.exists( this.getFullPath( path ) ); - } - - @Override - public boolean isDirectory( @Nonnull String path ) throws IOException - { - return this.parent.isDirectory( this.getFullPath( path ) ); - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - return this.parent.getSize( this.getFullPath( path ) ); + return parent.getAttributes( getFullPath( path ) ); } private String getFullPath( String path ) { - return path.isEmpty() ? this.subPath : this.subPath + "/" + path; + return path.isEmpty() ? subPath : subPath + "/" + path; } } diff --git a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java index edb8f695d..f515cd455 100644 --- a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java @@ -45,7 +45,7 @@ class BasicFunction extends VarArgFunction MethodResult results; try { - results = this.method.apply( this.instance, this.context, arguments ); + results = method.apply( instance, context, arguments ); } catch( LuaException e ) { @@ -55,7 +55,7 @@ class BasicFunction extends VarArgFunction { if( ComputerCraft.logComputerErrors ) { - ComputerCraft.log.error( "Error calling " + this.name + " on " + this.instance, t ); + ComputerCraft.log.error( "Error calling " + name + " on " + instance, t ); } throw new LuaError( "Java Exception Thrown: " + t, 0 ); } @@ -64,7 +64,7 @@ class BasicFunction extends VarArgFunction { throw new IllegalStateException( "Cannot have a yielding non-yielding function" ); } - return this.machine.toValues( results.getResult() ); + return machine.toValues( results.getResult() ); } public static LuaError wrap( LuaException exception ) diff --git a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java index 93d6b3737..54a7efdc6 100644 --- a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java +++ b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.lua; import dan200.computercraft.ComputerCraft; @@ -11,7 +10,6 @@ import dan200.computercraft.api.lua.*; import dan200.computercraft.core.asm.LuaMethod; import dan200.computercraft.core.asm.ObjectSource; import dan200.computercraft.core.computer.Computer; -import dan200.computercraft.core.computer.MainThread; import dan200.computercraft.core.computer.TimeoutState; import dan200.computercraft.core.tracking.Tracking; import dan200.computercraft.core.tracking.TrackingField; @@ -42,38 +40,39 @@ import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKYIELD; public class CobaltLuaMachine implements ILuaMachine { - private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor( 0, - Integer.MAX_VALUE, - 5L, - TimeUnit.MINUTES, + private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor( + 0, Integer.MAX_VALUE, + 5L, TimeUnit.MINUTES, new SynchronousQueue<>(), - ThreadUtils.factory( "Coroutine" ) ); + ThreadUtils.factory( "Coroutine" ) + ); private static final LuaMethod FUNCTION_METHOD = ( target, context, args ) -> ((ILuaFunction) target).call( args ); - private final Computer m_computer; + private final Computer computer; private final TimeoutState timeout; private final TimeoutDebugHandler debug; - private final ILuaContext context = new CobaltLuaContext(); + private final ILuaContext context; - private LuaState m_state; - private LuaTable m_globals; + private LuaState state; + private LuaTable globals; - private LuaThread m_mainRoutine = null; - private String m_eventFilter = null; + private LuaThread mainRoutine = null; + private String eventFilter = null; public CobaltLuaMachine( Computer computer, TimeoutState timeout ) { - this.m_computer = computer; + this.computer = computer; this.timeout = timeout; - this.debug = new TimeoutDebugHandler(); + this.context = new LuaContext( computer ); + debug = new TimeoutDebugHandler(); // Create an environment to run in - LuaState state = this.m_state = LuaState.builder() + LuaState state = this.state = LuaState.builder() .resourceManipulator( new VoidResourceManipulator() ) - .debug( this.debug ) + .debug( debug ) .coroutineExecutor( command -> { - Tracking.addValue( this.m_computer, TrackingField.COROUTINES_CREATED, 1 ); + Tracking.addValue( this.computer, TrackingField.COROUTINES_CREATED, 1 ); COROUTINES.execute( () -> { try { @@ -81,47 +80,278 @@ public class CobaltLuaMachine implements ILuaMachine } finally { - Tracking.addValue( this.m_computer, TrackingField.COROUTINES_DISPOSED, 1 ); + Tracking.addValue( this.computer, TrackingField.COROUTINES_DISPOSED, 1 ); } } ); } ) .build(); - this.m_globals = new LuaTable(); - state.setupThread( this.m_globals ); + globals = new LuaTable(); + state.setupThread( globals ); // Add basic libraries - this.m_globals.load( state, new BaseLib() ); - this.m_globals.load( state, new TableLib() ); - this.m_globals.load( state, new StringLib() ); - this.m_globals.load( state, new MathLib() ); - this.m_globals.load( state, new CoroutineLib() ); - this.m_globals.load( state, new Bit32Lib() ); - this.m_globals.load( state, new Utf8Lib() ); - if( ComputerCraft.debugEnable ) - { - this.m_globals.load( state, new DebugLib() ); - } + globals.load( state, new BaseLib() ); + globals.load( state, new TableLib() ); + globals.load( state, new StringLib() ); + globals.load( state, new MathLib() ); + globals.load( state, new CoroutineLib() ); + globals.load( state, new Bit32Lib() ); + globals.load( state, new Utf8Lib() ); + if( ComputerCraft.debugEnable ) globals.load( state, new DebugLib() ); // Remove globals we don't want to expose - this.m_globals.rawset( "collectgarbage", Constants.NIL ); - this.m_globals.rawset( "dofile", Constants.NIL ); - this.m_globals.rawset( "loadfile", Constants.NIL ); - this.m_globals.rawset( "print", Constants.NIL ); + globals.rawset( "collectgarbage", Constants.NIL ); + globals.rawset( "dofile", Constants.NIL ); + globals.rawset( "loadfile", Constants.NIL ); + globals.rawset( "print", Constants.NIL ); // Add version globals - this.m_globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) ); - this.m_globals.rawset( "_HOST", - valueOf( computer.getAPIEnvironment() - .getComputerEnvironment() - .getHostString() ) ); - this.m_globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.defaultComputerSettings ) ); + globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) ); + globals.rawset( "_HOST", valueOf( computer.getAPIEnvironment().getComputerEnvironment().getHostString() ) ); + globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.defaultComputerSettings ) ); if( ComputerCraft.disableLua51Features ) { - this.m_globals.rawset( "_CC_DISABLE_LUA51_FEATURES", Constants.TRUE ); + globals.rawset( "_CC_DISABLE_LUA51_FEATURES", Constants.TRUE ); } } + @Override + public void addAPI( @Nonnull ILuaAPI api ) + { + // Add the methods of an API to the global table + LuaTable table = wrapLuaObject( api ); + if( table == null ) + { + ComputerCraft.log.warn( "API {} does not provide any methods", api ); + table = new LuaTable(); + } + + String[] names = api.getNames(); + for( String name : names ) globals.rawset( name, table ); + } + + @Override + public MachineResult loadBios( @Nonnull InputStream bios ) + { + // Begin executing a file (ie, the bios) + if( mainRoutine != null ) return MachineResult.OK; + + try + { + LuaFunction value = LoadState.load( state, bios, "@bios.lua", globals ); + mainRoutine = new LuaThread( state, value, globals ); + return MachineResult.OK; + } + catch( CompileException e ) + { + close(); + return MachineResult.error( e ); + } + catch( Exception e ) + { + ComputerCraft.log.warn( "Could not load bios.lua", e ); + close(); + return MachineResult.GENERIC_ERROR; + } + } + + @Override + public MachineResult handleEvent( String eventName, Object[] arguments ) + { + if( mainRoutine == null ) return MachineResult.OK; + + if( eventFilter != null && eventName != null && !eventName.equals( eventFilter ) && !eventName.equals( "terminate" ) ) + { + return MachineResult.OK; + } + + // If the soft abort has been cleared then we can reset our flag. + timeout.refresh(); + if( !timeout.isSoftAborted() ) debug.thrownSoftAbort = false; + + try + { + Varargs resumeArgs = Constants.NONE; + if( eventName != null ) + { + resumeArgs = varargsOf( valueOf( eventName ), toValues( arguments ) ); + } + + // Resume the current thread, or the main one when first starting off. + LuaThread thread = state.getCurrentThread(); + if( thread == null || thread == state.getMainThread() ) thread = mainRoutine; + + Varargs results = LuaThread.run( thread, resumeArgs ); + if( timeout.isHardAborted() ) throw HardAbortError.INSTANCE; + if( results == null ) return MachineResult.PAUSE; + + LuaValue filter = results.first(); + eventFilter = filter.isString() ? filter.toString() : null; + + if( mainRoutine.getStatus().equals( "dead" ) ) + { + close(); + return MachineResult.GENERIC_ERROR; + } + else + { + return MachineResult.OK; + } + } + catch( HardAbortError | InterruptedException e ) + { + close(); + return MachineResult.TIMEOUT; + } + catch( LuaError e ) + { + close(); + ComputerCraft.log.warn( "Top level coroutine errored", e ); + return MachineResult.error( e ); + } + } + + @Override + public void close() + { + LuaState state = this.state; + if( state == null ) return; + + state.abandon(); + mainRoutine = null; + this.state = null; + globals = null; + } + + @Nullable + private LuaTable wrapLuaObject( Object object ) + { + String[] dynamicMethods = object instanceof IDynamicLuaObject + ? Objects.requireNonNull( ((IDynamicLuaObject) object).getMethodNames(), "Methods cannot be null" ) + : LuaMethod.EMPTY_METHODS; + + LuaTable table = new LuaTable(); + for( int i = 0; i < dynamicMethods.length; i++ ) + { + String method = dynamicMethods[i]; + table.rawset( method, new ResultInterpreterFunction( this, LuaMethod.DYNAMIC.get( i ), object, context, method ) ); + } + + ObjectSource.allMethods( LuaMethod.GENERATOR, object, ( instance, method ) -> + table.rawset( method.getName(), method.nonYielding() + ? new BasicFunction( this, method.getMethod(), instance, context, method.getName() ) + : new ResultInterpreterFunction( this, method.getMethod(), instance, context, method.getName() ) ) ); + + try + { + if( table.keyCount() == 0 ) return null; + } + catch( LuaError ignored ) + { + } + + return table; + } + + @Nonnull + private LuaValue toValue( @Nullable Object object, @Nullable Map values ) + { + if( object == null ) return Constants.NIL; + if( object instanceof Number ) return valueOf( ((Number) object).doubleValue() ); + if( object instanceof Boolean ) return valueOf( (Boolean) object ); + if( object instanceof String ) return valueOf( object.toString() ); + if( object instanceof byte[] ) + { + byte[] b = (byte[]) object; + return valueOf( Arrays.copyOf( b, b.length ) ); + } + if( object instanceof ByteBuffer ) + { + ByteBuffer b = (ByteBuffer) object; + byte[] bytes = new byte[b.remaining()]; + b.get( bytes ); + return valueOf( bytes ); + } + + if( values == null ) values = new IdentityHashMap<>( 1 ); + LuaValue result = values.get( object ); + if( result != null ) return result; + + if( object instanceof ILuaFunction ) + { + return new ResultInterpreterFunction( this, FUNCTION_METHOD, object, context, object.toString() ); + } + + if( object instanceof IDynamicLuaObject ) + { + LuaValue wrapped = wrapLuaObject( object ); + if( wrapped == null ) wrapped = new LuaTable(); + values.put( object, wrapped ); + return wrapped; + } + + if( object instanceof Map ) + { + LuaTable table = new LuaTable(); + values.put( object, table ); + + for( Map.Entry pair : ((Map) object).entrySet() ) + { + LuaValue key = toValue( pair.getKey(), values ); + LuaValue value = toValue( pair.getValue(), values ); + if( !key.isNil() && !value.isNil() ) table.rawset( key, value ); + } + return table; + } + + if( object instanceof Collection ) + { + Collection objects = (Collection) object; + LuaTable table = new LuaTable( objects.size(), 0 ); + values.put( object, table ); + int i = 0; + for( Object child : objects ) table.rawset( ++i, toValue( child, values ) ); + return table; + } + + if( object instanceof Object[] ) + { + Object[] objects = (Object[]) object; + LuaTable table = new LuaTable( objects.length, 0 ); + values.put( object, table ); + for( int i = 0; i < objects.length; i++ ) table.rawset( i + 1, toValue( objects[i], values ) ); + return table; + } + + LuaTable wrapped = wrapLuaObject( object ); + if( wrapped != null ) + { + values.put( object, wrapped ); + return wrapped; + } + + if( ComputerCraft.logComputerErrors ) + { + ComputerCraft.log.warn( "Received unknown type '{}', returning nil.", object.getClass().getName() ); + } + return Constants.NIL; + } + + Varargs toValues( Object[] objects ) + { + if( objects == null || objects.length == 0 ) return Constants.NONE; + if( objects.length == 1 ) return toValue( objects[0], null ); + + Map result = new IdentityHashMap<>( 0 ); + LuaValue[] values = new LuaValue[objects.length]; + for( int i = 0; i < values.length; i++ ) + { + Object object = objects[i]; + values[i] = toValue( object, result ); + } + return varargsOf( values ); + } + static Object toObject( LuaValue value, Map objects ) { switch( value.type() ) @@ -147,10 +377,7 @@ public class CobaltLuaMachine implements ILuaMachine else { Object existing = objects.get( value ); - if( existing != null ) - { - return existing; - } + if( existing != null ) return existing; } Map table = new HashMap<>(); objects.put( value, table ); @@ -171,10 +398,7 @@ public class CobaltLuaMachine implements ILuaMachine break; } k = keyValue.first(); - if( k.isNil() ) - { - break; - } + if( k.isNil() ) break; LuaValue v = keyValue.arg( 2 ); Object keyObject = toObject( k, objects ); @@ -195,10 +419,7 @@ public class CobaltLuaMachine implements ILuaMachine { int count = values.count(); Object[] objects = new Object[count]; - for( int i = 0; i < count; i++ ) - { - objects[i] = toObject( values.arg( i + 1 ), null ); - } + for( int i = 0; i < count; i++ ) objects[i] = toObject( values.arg( i + 1 ), null ); return objects; } @@ -207,342 +428,22 @@ public class CobaltLuaMachine implements ILuaMachine return values == Constants.NONE ? VarargArguments.EMPTY : new VarargArguments( values ); } - @Override - public void addAPI( @Nonnull ILuaAPI api ) - { - // Add the methods of an API to the global table - LuaTable table = this.wrapLuaObject( api ); - if( table == null ) - { - ComputerCraft.log.warn( "API {} does not provide any methods", api ); - table = new LuaTable(); - } - - String[] names = api.getNames(); - for( String name : names ) - { - this.m_globals.rawset( name, table ); - } - } - - @Override - public MachineResult loadBios( @Nonnull InputStream bios ) - { - // Begin executing a file (ie, the bios) - if( this.m_mainRoutine != null ) - { - return MachineResult.OK; - } - - try - { - LuaFunction value = LoadState.load( this.m_state, bios, "@bios.lua", this.m_globals ); - this.m_mainRoutine = new LuaThread( this.m_state, value, this.m_globals ); - return MachineResult.OK; - } - catch( CompileException e ) - { - this.close(); - return MachineResult.error( e ); - } - catch( Exception e ) - { - ComputerCraft.log.warn( "Could not load bios.lua", e ); - this.close(); - return MachineResult.GENERIC_ERROR; - } - } - - @Override - public MachineResult handleEvent( String eventName, Object[] arguments ) - { - if( this.m_mainRoutine == null ) - { - return MachineResult.OK; - } - - if( this.m_eventFilter != null && eventName != null && !eventName.equals( this.m_eventFilter ) && !eventName.equals( "terminate" ) ) - { - return MachineResult.OK; - } - - // If the soft abort has been cleared then we can reset our flag. - this.timeout.refresh(); - if( !this.timeout.isSoftAborted() ) - { - this.debug.thrownSoftAbort = false; - } - - try - { - Varargs resumeArgs = Constants.NONE; - if( eventName != null ) - { - resumeArgs = varargsOf( valueOf( eventName ), this.toValues( arguments ) ); - } - - // Resume the current thread, or the main one when first starting off. - LuaThread thread = this.m_state.getCurrentThread(); - if( thread == null || thread == this.m_state.getMainThread() ) - { - thread = this.m_mainRoutine; - } - - Varargs results = LuaThread.run( thread, resumeArgs ); - if( this.timeout.isHardAborted() ) - { - throw HardAbortError.INSTANCE; - } - if( results == null ) - { - return MachineResult.PAUSE; - } - - LuaValue filter = results.first(); - this.m_eventFilter = filter.isString() ? filter.toString() : null; - - if( this.m_mainRoutine.getStatus() - .equals( "dead" ) ) - { - this.close(); - return MachineResult.GENERIC_ERROR; - } - else - { - return MachineResult.OK; - } - } - catch( HardAbortError | InterruptedException e ) - { - this.close(); - return MachineResult.TIMEOUT; - } - catch( LuaError e ) - { - this.close(); - ComputerCraft.log.warn( "Top level coroutine errored", e ); - return MachineResult.error( e ); - } - } - - @Override - public void close() - { - LuaState state = this.m_state; - if( state == null ) - { - return; - } - - state.abandon(); - this.m_mainRoutine = null; - this.m_state = null; - this.m_globals = null; - } - - @Nullable - private LuaTable wrapLuaObject( Object object ) - { - String[] dynamicMethods = object instanceof IDynamicLuaObject ? Objects.requireNonNull( ((IDynamicLuaObject) object).getMethodNames(), - "Methods cannot be null" ) : LuaMethod.EMPTY_METHODS; - - LuaTable table = new LuaTable(); - for( int i = 0; i < dynamicMethods.length; i++ ) - { - String method = dynamicMethods[i]; - table.rawset( method, new ResultInterpreterFunction( this, LuaMethod.DYNAMIC.get( i ), object, this.context, method ) ); - } - - ObjectSource.allMethods( LuaMethod.GENERATOR, - object, - ( instance, method ) -> table.rawset( method.getName(), - method.nonYielding() ? new BasicFunction( this, - (LuaMethod) method.getMethod(), - instance, this.context, - method.getName() ) : - new ResultInterpreterFunction( - this, - (LuaMethod) method.getMethod(), - instance, this.context, - method.getName() ) ) ); - - try - { - if( table.keyCount() == 0 ) - { - return null; - } - } - catch( LuaError ignored ) - { - } - - return table; - } - - @Nonnull - private LuaValue toValue( @Nullable Object object, @Nullable Map values ) - { - if( object == null ) - { - return Constants.NIL; - } - if( object instanceof Number ) - { - return valueOf( ((Number) object).doubleValue() ); - } - if( object instanceof Boolean ) - { - return valueOf( (Boolean) object ); - } - if( object instanceof String ) - { - return valueOf( object.toString() ); - } - if( object instanceof byte[] ) - { - byte[] b = (byte[]) object; - return valueOf( Arrays.copyOf( b, b.length ) ); - } - if( object instanceof ByteBuffer ) - { - ByteBuffer b = (ByteBuffer) object; - byte[] bytes = new byte[b.remaining()]; - b.get( bytes ); - return valueOf( bytes ); - } - - if( values == null ) - { - values = new IdentityHashMap<>( 1 ); - } - LuaValue result = values.get( object ); - if( result != null ) - { - return result; - } - - if( object instanceof ILuaFunction ) - { - return new ResultInterpreterFunction( this, FUNCTION_METHOD, object, this.context, object.toString() ); - } - - if( object instanceof IDynamicLuaObject ) - { - LuaValue wrapped = this.wrapLuaObject( object ); - if( wrapped == null ) - { - wrapped = new LuaTable(); - } - values.put( object, wrapped ); - return wrapped; - } - - if( object instanceof Map ) - { - LuaTable table = new LuaTable(); - values.put( object, table ); - - for( Map.Entry pair : ((Map) object).entrySet() ) - { - LuaValue key = this.toValue( pair.getKey(), values ); - LuaValue value = this.toValue( pair.getValue(), values ); - if( !key.isNil() && !value.isNil() ) - { - table.rawset( key, value ); - } - } - return table; - } - - if( object instanceof Collection ) - { - Collection objects = (Collection) object; - LuaTable table = new LuaTable( objects.size(), 0 ); - values.put( object, table ); - int i = 0; - for( Object child : objects ) - { - table.rawset( ++i, this.toValue( child, values ) ); - } - return table; - } - - if( object instanceof Object[] ) - { - Object[] objects = (Object[]) object; - LuaTable table = new LuaTable( objects.length, 0 ); - values.put( object, table ); - for( int i = 0; i < objects.length; i++ ) - { - table.rawset( i + 1, this.toValue( objects[i], values ) ); - } - return table; - } - - LuaTable wrapped = this.wrapLuaObject( object ); - if( wrapped != null ) - { - values.put( object, wrapped ); - return wrapped; - } - - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.warn( "Received unknown type '{}', returning nil.", - object.getClass() - .getName() ); - } - return Constants.NIL; - } - - Varargs toValues( Object[] objects ) - { - if( objects == null || objects.length == 0 ) - { - return Constants.NONE; - } - if( objects.length == 1 ) - { - return this.toValue( objects[0], null ); - } - - Map result = new IdentityHashMap<>( 0 ); - LuaValue[] values = new LuaValue[objects.length]; - for( int i = 0; i < values.length; i++ ) - { - Object object = objects[i]; - values[i] = this.toValue( object, result ); - } - return varargsOf( values ); - } - - private static final class HardAbortError extends Error - { - static final HardAbortError INSTANCE = new HardAbortError(); - private static final long serialVersionUID = 7954092008586367501L; - - private HardAbortError() - { - super( "Hard Abort", null, true, false ); - } - } - /** * A {@link DebugHandler} which observes the {@link TimeoutState} and responds accordingly. */ private class TimeoutDebugHandler extends DebugHandler { private final TimeoutState timeout; - boolean thrownSoftAbort; private int count = 0; + boolean thrownSoftAbort; + private boolean isPaused; private int oldFlags; private boolean oldInHook; TimeoutDebugHandler() { - this.timeout = CobaltLuaMachine.this.timeout; + timeout = CobaltLuaMachine.this.timeout; } @Override @@ -550,35 +451,29 @@ public class CobaltLuaMachine implements ILuaMachine { di.pc = pc; - if( this.isPaused ) - { - this.resetPaused( ds, di ); - } + if( isPaused ) resetPaused( ds, di ); // We check our current pause/abort state every 128 instructions. - if( (this.count = (this.count + 1) & 127) == 0 ) + if( (count = (count + 1) & 127) == 0 ) { // If we've been hard aborted or closed then abort. - if( this.timeout.isHardAborted() || CobaltLuaMachine.this.m_state == null ) - { - throw HardAbortError.INSTANCE; - } + if( timeout.isHardAborted() || state == null ) throw HardAbortError.INSTANCE; - this.timeout.refresh(); - if( this.timeout.isPaused() ) + timeout.refresh(); + if( timeout.isPaused() ) { // Preserve the current state - this.isPaused = true; - this.oldInHook = ds.inhook; - this.oldFlags = di.flags; + isPaused = true; + oldInHook = ds.inhook; + oldFlags = di.flags; // Suspend the state. This will probably throw, but we need to handle the case where it won't. di.flags |= FLAG_HOOKYIELD | FLAG_HOOKED; LuaThread.suspend( ds.getLuaState() ); - this.resetPaused( ds, di ); + resetPaused( ds, di ); } - this.handleSoftAbort(); + handleSoftAbort(); } super.onInstruction( ds, di, pc ); @@ -588,99 +483,41 @@ public class CobaltLuaMachine implements ILuaMachine public void poll() throws LuaError { // If we've been hard aborted or closed then abort. - LuaState state = CobaltLuaMachine.this.m_state; - if( this.timeout.isHardAborted() || state == null ) - { - throw HardAbortError.INSTANCE; - } + LuaState state = CobaltLuaMachine.this.state; + if( timeout.isHardAborted() || state == null ) throw HardAbortError.INSTANCE; - this.timeout.refresh(); - if( this.timeout.isPaused() ) - { - LuaThread.suspendBlocking( state ); - } - this.handleSoftAbort(); + timeout.refresh(); + if( timeout.isPaused() ) LuaThread.suspendBlocking( state ); + handleSoftAbort(); } private void resetPaused( DebugState ds, DebugFrame di ) { // Restore the previous paused state - this.isPaused = false; - ds.inhook = this.oldInHook; - di.flags = this.oldFlags; + isPaused = false; + ds.inhook = oldInHook; + di.flags = oldFlags; } private void handleSoftAbort() throws LuaError { // If we already thrown our soft abort error then don't do it again. - if( !this.timeout.isSoftAborted() || this.thrownSoftAbort ) - { - return; - } + if( !timeout.isSoftAborted() || thrownSoftAbort ) return; - this.thrownSoftAbort = true; + thrownSoftAbort = true; throw new LuaError( TimeoutState.ABORT_MESSAGE ); } } - private class CobaltLuaContext implements ILuaContext + private static final class HardAbortError extends Error { - @Override - public long issueMainThreadTask( @Nonnull final ILuaTask task ) throws LuaException + private static final long serialVersionUID = 7954092008586367501L; + + static final HardAbortError INSTANCE = new HardAbortError(); + + private HardAbortError() { - // Issue command - final long taskID = MainThread.getUniqueTaskID(); - final Runnable iTask = () -> { - try - { - Object[] results = task.execute(); - if( results != null ) - { - Object[] eventArguments = new Object[results.length + 2]; - eventArguments[0] = taskID; - eventArguments[1] = true; - System.arraycopy( results, 0, eventArguments, 2, results.length ); - CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", eventArguments ); - } - else - { - CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", - new Object[] { - taskID, - true - } ); - } - } - catch( LuaException e ) - { - CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", - new Object[] { - taskID, - false, - e.getMessage() - } ); - } - catch( Throwable t ) - { - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.error( "Error running task", t ); - } - CobaltLuaMachine.this.m_computer.queueEvent( "task_complete", new Object[] { - taskID, - false, - "Java Exception Thrown: " + t, - } ); - } - }; - if( CobaltLuaMachine.this.m_computer.queueMainThread( iTask ) ) - { - return taskID; - } - else - { - throw new LuaException( "Task limit exceeded" ); - } + super( "Hard Abort", null, true, false ); } } } diff --git a/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java b/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java index 272a8d3ee..3d62c2c43 100644 --- a/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java +++ b/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.lua; import dan200.computercraft.api.lua.IDynamicLuaObject; @@ -14,20 +13,21 @@ import javax.annotation.Nullable; import java.io.InputStream; /** - * Represents a machine which will execute Lua code. Technically this API is flexible enough to support many languages, but you'd need a way to provide - * alternative ROMs, BIOSes, etc... + * Represents a machine which will execute Lua code. Technically this API is flexible enough to support many languages, + * but you'd need a way to provide alternative ROMs, BIOSes, etc... * - * There should only be one concrete implementation at any one time, which is currently {@link CobaltLuaMachine}. If external mod authors are interested in - * registering their own machines, we can look into how we can provide some mechanism for registering these. + * There should only be one concrete implementation at any one time, which is currently {@link CobaltLuaMachine}. If + * external mod authors are interested in registering their own machines, we can look into how we can provide some + * mechanism for registering these. * - * This should provide implementations of {@link dan200.computercraft.api.lua.ILuaContext}, and the ability to convert {@link IDynamicLuaObject}s into - * something the VM understands, as well as handling method calls. + * This should provide implementations of {@link dan200.computercraft.api.lua.ILuaContext}, and the ability to convert + * {@link IDynamicLuaObject}s into something the VM understands, as well as handling method calls. */ public interface ILuaMachine { /** - * Inject an API into the global environment of this machine. This should construct an object, as it would for any {@link IDynamicLuaObject} and set it - * to all names in {@link ILuaAPI#getNames()}. + * Inject an API into the global environment of this machine. This should construct an object, as it would for any + * {@link IDynamicLuaObject} and set it to all names in {@link ILuaAPI#getNames()}. * * Called before {@link #loadBios(InputStream)}. * @@ -36,7 +36,8 @@ public interface ILuaMachine void addAPI( @Nonnull ILuaAPI api ); /** - * Create a function from the provided program, and set it up to run when {@link #handleEvent(String, Object[])} is called. + * Create a function from the provided program, and set it up to run when {@link #handleEvent(String, Object[])} is + * called. * * This should destroy the machine if it failed to load the bios. * @@ -50,10 +51,11 @@ public interface ILuaMachine * * This should destroy the machine if it failed to execute successfully. * - * @param eventName The name of the event. This is {@code null} when first starting the machine. Note, this may do nothing if it does not match the - * event filter. + * @param eventName The name of the event. This is {@code null} when first starting the machine. Note, this may + * do nothing if it does not match the event filter. * @param arguments The arguments for this event. - * @return The result of loading this machine. Will either be OK, or the error message that occurred when executing. + * @return The result of loading this machine. Will either be OK, or the error message that occurred when + * executing. */ MachineResult handleEvent( @Nullable String eventName, @Nullable Object[] arguments ); diff --git a/src/main/java/dan200/computercraft/core/lua/LuaContext.java b/src/main/java/dan200/computercraft/core/lua/LuaContext.java new file mode 100644 index 000000000..626d15fad --- /dev/null +++ b/src/main/java/dan200/computercraft/core/lua/LuaContext.java @@ -0,0 +1,69 @@ +/* + * 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.core.lua; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.ILuaTask; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.core.computer.Computer; +import dan200.computercraft.core.computer.MainThread; + +import javax.annotation.Nonnull; + +class LuaContext implements ILuaContext +{ + private final Computer computer; + + LuaContext( Computer computer ) + { + this.computer = computer; + } + + @Override + public long issueMainThreadTask( @Nonnull final ILuaTask task ) throws LuaException + { + // Issue command + final long taskID = MainThread.getUniqueTaskID(); + final Runnable iTask = () -> { + try + { + Object[] results = task.execute(); + if( results != null ) + { + Object[] eventArguments = new Object[results.length + 2]; + eventArguments[0] = taskID; + eventArguments[1] = true; + System.arraycopy( results, 0, eventArguments, 2, results.length ); + computer.queueEvent( "task_complete", eventArguments ); + } + else + { + computer.queueEvent( "task_complete", new Object[] { taskID, true } ); + } + } + catch( LuaException e ) + { + computer.queueEvent( "task_complete", new Object[] { taskID, false, e.getMessage() } ); + } + catch( Exception t ) + { + if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error running task", t ); + computer.queueEvent( "task_complete", new Object[] { + taskID, false, "Java Exception Thrown: " + t, + } ); + } + }; + if( computer.queueMainThread( iTask ) ) + { + return taskID; + } + else + { + throw new LuaException( "Task limit exceeded" ); + } + } +} diff --git a/src/main/java/dan200/computercraft/core/lua/MachineResult.java b/src/main/java/dan200/computercraft/core/lua/MachineResult.java index f5cc1058b..167ec9298 100644 --- a/src/main/java/dan200/computercraft/core/lua/MachineResult.java +++ b/src/main/java/dan200/computercraft/core/lua/MachineResult.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.lua; import dan200.computercraft.core.computer.TimeoutState; @@ -65,17 +64,17 @@ public final class MachineResult public boolean isError() { - return this.error; + return error; } public boolean isPause() { - return this.pause; + return pause; } @Nullable public String getMessage() { - return this.message; + return message; } } diff --git a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java index 90b6bd70b..495d1a2d1 100644 --- a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java @@ -15,11 +15,24 @@ import org.squiddev.cobalt.function.ResumableVarArgFunction; import javax.annotation.Nonnull; /** - * Calls a {@link LuaMethod}, and interprets the resulting {@link MethodResult}, either returning the result or yielding and resuming the supplied - * continuation. + * Calls a {@link LuaMethod}, and interprets the resulting {@link MethodResult}, either returning the result or yielding + * and resuming the supplied continuation. */ class ResultInterpreterFunction extends ResumableVarArgFunction { + @Nonnull + static class Container + { + ILuaCallback callback; + int errorAdjust; + + Container( ILuaCallback callback, int errorAdjust ) + { + this.callback = callback; + this.errorAdjust = errorAdjust; + } + } + private final CobaltLuaMachine machine; private final LuaMethod method; private final Object instance; @@ -42,7 +55,7 @@ class ResultInterpreterFunction extends ResumableVarArgFunction= this.varargs.count() ) - { - return null; - } + if( index < 0 || index >= varargs.count() ) return null; Object[] cache = this.cache; if( cache == null ) { - cache = this.cache = new Object[this.varargs.count()]; + cache = this.cache = new Object[varargs.count()]; } else { Object existing = cache[index]; - if( existing != null ) - { - return existing; - } + if( existing != null ) return existing; } - return cache[index] = CobaltLuaMachine.toObject( this.varargs.arg( index + 1 ), null ); + return cache[index] = CobaltLuaMachine.toObject( varargs.arg( index + 1 ), null ); } @Override - public long getLong( int index ) throws LuaException + public IArguments drop( int count ) { - LuaValue value = this.varargs.arg( index + 1 ); - if( !(value instanceof LuaNumber) ) - { - throw LuaValues.badArgument( index, "number", value.typeName() ); - } - return value instanceof LuaInteger ? value.toInteger() : (long) LuaValues.checkFinite( index, value.toDouble() ); + if( count < 0 ) throw new IllegalStateException( "count cannot be negative" ); + if( count == 0 ) return this; + return new VarargArguments( varargs.subargs( count + 1 ) ); } @Override public double getDouble( int index ) throws LuaException { - LuaValue value = this.varargs.arg( index + 1 ); - if( !(value instanceof LuaNumber) ) - { - throw LuaValues.badArgument( index, "number", value.typeName() ); - } + LuaValue value = varargs.arg( index + 1 ); + if( !(value instanceof LuaNumber) ) throw LuaValues.badArgument( index, "number", value.typeName() ); return value.toDouble(); } + @Override + public long getLong( int index ) throws LuaException + { + LuaValue value = varargs.arg( index + 1 ); + if( !(value instanceof LuaNumber) ) throw LuaValues.badArgument( index, "number", value.typeName() ); + return value instanceof LuaInteger ? value.toInteger() : (long) LuaValues.checkFinite( index, value.toDouble() ); + } + @Nonnull @Override public ByteBuffer getBytes( int index ) throws LuaException { - LuaValue value = this.varargs.arg( index + 1 ); - if( !(value instanceof LuaBaseString) ) - { - throw LuaValues.badArgument( index, "string", value.typeName() ); - } + LuaValue value = varargs.arg( index + 1 ); + if( !(value instanceof LuaBaseString) ) throw LuaValues.badArgument( index, "string", value.typeName() ); LuaString str = ((LuaBaseString) value).strvalue(); - return ByteBuffer.wrap( str.bytes, str.offset, str.length ) - .asReadOnlyBuffer(); + return ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer(); } @Override public Optional optBytes( int index ) throws LuaException { - LuaValue value = this.varargs.arg( index + 1 ); - if( value.isNil() ) - { - return Optional.empty(); - } - if( !(value instanceof LuaBaseString) ) - { - throw LuaValues.badArgument( index, "string", value.typeName() ); - } + LuaValue value = varargs.arg( index + 1 ); + if( value.isNil() ) return Optional.empty(); + if( !(value instanceof LuaBaseString) ) throw LuaValues.badArgument( index, "string", value.typeName() ); LuaString str = ((LuaBaseString) value).strvalue(); - return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ) - .asReadOnlyBuffer() ); + return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer() ); } } diff --git a/src/main/java/dan200/computercraft/core/terminal/Terminal.java b/src/main/java/dan200/computercraft/core/terminal/Terminal.java index 08fe1d01f..d09e984de 100644 --- a/src/main/java/dan200/computercraft/core/terminal/Terminal.java +++ b/src/main/java/dan200/computercraft/core/terminal/Terminal.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.terminal; import dan200.computercraft.shared.util.Colour; @@ -16,18 +15,23 @@ import javax.annotation.Nonnull; public class Terminal { private static final String base16 = "0123456789abcdef"; - private final Palette m_palette = new Palette(); + + private int cursorX = 0; + private int cursorY = 0; + private boolean cursorBlink = false; + private int cursorColour = 0; + private int cursorBackgroundColour = 15; + + private int width; + private int height; + + private TextBuffer[] text; + private TextBuffer[] textColour; + private TextBuffer[] backgroundColour; + + private final Palette palette = new Palette(); + private final Runnable onChanged; - private int m_cursorX = 0; - private int m_cursorY = 0; - private boolean m_cursorBlink = false; - private int m_cursorColour = 0; - private int m_cursorBackgroundColour = 15; - private int m_width; - private int m_height; - private TextBuffer[] m_text; - private TextBuffer[] m_textColour; - private TextBuffer[] m_backgroundColour; public Terminal( int width, int height ) { @@ -36,199 +40,180 @@ public class Terminal public Terminal( int width, int height, Runnable changedCallback ) { - this.m_width = width; - this.m_height = height; - this.onChanged = changedCallback; + this.width = width; + this.height = height; + onChanged = changedCallback; - this.m_text = new TextBuffer[this.m_height]; - this.m_textColour = new TextBuffer[this.m_height]; - this.m_backgroundColour = new TextBuffer[this.m_height]; - for( int i = 0; i < this.m_height; i++ ) + text = new TextBuffer[this.height]; + textColour = new TextBuffer[this.height]; + backgroundColour = new TextBuffer[this.height]; + for( int i = 0; i < this.height; i++ ) { - this.m_text[i] = new TextBuffer( ' ', this.m_width ); - this.m_textColour[i] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); - this.m_backgroundColour[i] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); + text[i] = new TextBuffer( ' ', this.width ); + textColour[i] = new TextBuffer( base16.charAt( cursorColour ), this.width ); + backgroundColour[i] = new TextBuffer( base16.charAt( cursorBackgroundColour ), this.width ); } } public synchronized void reset() { - this.m_cursorColour = 0; - this.m_cursorBackgroundColour = 15; - this.m_cursorX = 0; - this.m_cursorY = 0; - this.m_cursorBlink = false; - this.clear(); - this.setChanged(); - this.m_palette.resetColours(); - } - - public synchronized void clear() - { - for( int y = 0; y < this.m_height; y++ ) - { - this.m_text[y].fill( ' ' ); - this.m_textColour[y].fill( base16.charAt( this.m_cursorColour ) ); - this.m_backgroundColour[y].fill( base16.charAt( this.m_cursorBackgroundColour ) ); - } - this.setChanged(); - } - - public final void setChanged() - { - if( this.onChanged != null ) - { - this.onChanged.run(); - } + cursorColour = 0; + cursorBackgroundColour = 15; + cursorX = 0; + cursorY = 0; + cursorBlink = false; + clear(); + setChanged(); + palette.resetColours(); } public int getWidth() { - return this.m_width; + return width; } public int getHeight() { - return this.m_height; + return height; } public synchronized void resize( int width, int height ) { - if( width == this.m_width && height == this.m_height ) + if( width == this.width && height == this.height ) { return; } - int oldHeight = this.m_height; - int oldWidth = this.m_width; - TextBuffer[] oldText = this.m_text; - TextBuffer[] oldTextColour = this.m_textColour; - TextBuffer[] oldBackgroundColour = this.m_backgroundColour; + int oldHeight = this.height; + int oldWidth = this.width; + TextBuffer[] oldText = text; + TextBuffer[] oldTextColour = textColour; + TextBuffer[] oldBackgroundColour = backgroundColour; - this.m_width = width; - this.m_height = height; + this.width = width; + this.height = height; - this.m_text = new TextBuffer[this.m_height]; - this.m_textColour = new TextBuffer[this.m_height]; - this.m_backgroundColour = new TextBuffer[this.m_height]; - for( int i = 0; i < this.m_height; i++ ) + text = new TextBuffer[this.height]; + textColour = new TextBuffer[this.height]; + backgroundColour = new TextBuffer[this.height]; + for( int i = 0; i < this.height; i++ ) { if( i >= oldHeight ) { - this.m_text[i] = new TextBuffer( ' ', this.m_width ); - this.m_textColour[i] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); - this.m_backgroundColour[i] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); + text[i] = new TextBuffer( ' ', this.width ); + textColour[i] = new TextBuffer( base16.charAt( cursorColour ), this.width ); + backgroundColour[i] = new TextBuffer( base16.charAt( cursorBackgroundColour ), this.width ); } - else if( this.m_width == oldWidth ) + else if( this.width == oldWidth ) { - this.m_text[i] = oldText[i]; - this.m_textColour[i] = oldTextColour[i]; - this.m_backgroundColour[i] = oldBackgroundColour[i]; + text[i] = oldText[i]; + textColour[i] = oldTextColour[i]; + backgroundColour[i] = oldBackgroundColour[i]; } else { - this.m_text[i] = new TextBuffer( ' ', this.m_width ); - this.m_textColour[i] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); - this.m_backgroundColour[i] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); - this.m_text[i].write( oldText[i] ); - this.m_textColour[i].write( oldTextColour[i] ); - this.m_backgroundColour[i].write( oldBackgroundColour[i] ); + text[i] = new TextBuffer( ' ', this.width ); + textColour[i] = new TextBuffer( base16.charAt( cursorColour ), this.width ); + backgroundColour[i] = new TextBuffer( base16.charAt( cursorBackgroundColour ), this.width ); + text[i].write( oldText[i] ); + textColour[i].write( oldTextColour[i] ); + backgroundColour[i].write( oldBackgroundColour[i] ); } } - this.setChanged(); + setChanged(); } public void setCursorPos( int x, int y ) { - if( this.m_cursorX != x || this.m_cursorY != y ) + if( cursorX != x || cursorY != y ) { - this.m_cursorX = x; - this.m_cursorY = y; - this.setChanged(); + cursorX = x; + cursorY = y; + setChanged(); + } + } + + public void setCursorBlink( boolean blink ) + { + if( cursorBlink != blink ) + { + cursorBlink = blink; + setChanged(); + } + } + + public void setTextColour( int colour ) + { + if( cursorColour != colour ) + { + cursorColour = colour; + setChanged(); + } + } + + public void setBackgroundColour( int colour ) + { + if( cursorBackgroundColour != colour ) + { + cursorBackgroundColour = colour; + setChanged(); } } public int getCursorX() { - return this.m_cursorX; + return cursorX; } public int getCursorY() { - return this.m_cursorY; + return cursorY; } public boolean getCursorBlink() { - return this.m_cursorBlink; - } - - public void setCursorBlink( boolean blink ) - { - if( this.m_cursorBlink != blink ) - { - this.m_cursorBlink = blink; - this.setChanged(); - } + return cursorBlink; } public int getTextColour() { - return this.m_cursorColour; - } - - public void setTextColour( int colour ) - { - if( this.m_cursorColour != colour ) - { - this.m_cursorColour = colour; - this.setChanged(); - } + return cursorColour; } public int getBackgroundColour() { - return this.m_cursorBackgroundColour; - } - - public void setBackgroundColour( int colour ) - { - if( this.m_cursorBackgroundColour != colour ) - { - this.m_cursorBackgroundColour = colour; - this.setChanged(); - } + return cursorBackgroundColour; } @Nonnull public Palette getPalette() { - return this.m_palette; + return palette; } public synchronized void blit( String text, String textColour, String backgroundColour ) { - int x = this.m_cursorX; - int y = this.m_cursorY; - if( y >= 0 && y < this.m_height ) + int x = cursorX; + int y = cursorY; + if( y >= 0 && y < height ) { - this.m_text[y].write( text, x ); - this.m_textColour[y].write( textColour, x ); - this.m_backgroundColour[y].write( backgroundColour, x ); - this.setChanged(); + this.text[y].write( text, x ); + this.textColour[y].write( textColour, x ); + this.backgroundColour[y].write( backgroundColour, x ); + setChanged(); } } public synchronized void write( String text ) { - int x = this.m_cursorX; - int y = this.m_cursorY; - if( y >= 0 && y < this.m_height ) + int x = cursorX; + int y = cursorY; + if( y >= 0 && y < height ) { - this.m_text[y].write( text, x ); - this.m_textColour[y].fill( base16.charAt( this.m_cursorColour ), x, x + text.length() ); - this.m_backgroundColour[y].fill( base16.charAt( this.m_cursorBackgroundColour ), x, x + text.length() ); - this.setChanged(); + this.text[y].write( text, x ); + textColour[y].fill( base16.charAt( cursorColour ), x, x + text.length() ); + backgroundColour[y].fill( base16.charAt( cursorBackgroundColour ), x, x + text.length() ); + setChanged(); } } @@ -236,132 +221,138 @@ public class Terminal { if( yDiff != 0 ) { - TextBuffer[] newText = new TextBuffer[this.m_height]; - TextBuffer[] newTextColour = new TextBuffer[this.m_height]; - TextBuffer[] newBackgroundColour = new TextBuffer[this.m_height]; - for( int y = 0; y < this.m_height; y++ ) + TextBuffer[] newText = new TextBuffer[height]; + TextBuffer[] newTextColour = new TextBuffer[height]; + TextBuffer[] newBackgroundColour = new TextBuffer[height]; + for( int y = 0; y < height; y++ ) { int oldY = y + yDiff; - if( oldY >= 0 && oldY < this.m_height ) + if( oldY >= 0 && oldY < height ) { - newText[y] = this.m_text[oldY]; - newTextColour[y] = this.m_textColour[oldY]; - newBackgroundColour[y] = this.m_backgroundColour[oldY]; + newText[y] = text[oldY]; + newTextColour[y] = textColour[oldY]; + newBackgroundColour[y] = backgroundColour[oldY]; } else { - newText[y] = new TextBuffer( ' ', this.m_width ); - newTextColour[y] = new TextBuffer( base16.charAt( this.m_cursorColour ), this.m_width ); - newBackgroundColour[y] = new TextBuffer( base16.charAt( this.m_cursorBackgroundColour ), this.m_width ); + newText[y] = new TextBuffer( ' ', width ); + newTextColour[y] = new TextBuffer( base16.charAt( cursorColour ), width ); + newBackgroundColour[y] = new TextBuffer( base16.charAt( cursorBackgroundColour ), width ); } } - this.m_text = newText; - this.m_textColour = newTextColour; - this.m_backgroundColour = newBackgroundColour; - this.setChanged(); + text = newText; + textColour = newTextColour; + backgroundColour = newBackgroundColour; + setChanged(); } } + public synchronized void clear() + { + for( int y = 0; y < height; y++ ) + { + text[y].fill( ' ' ); + textColour[y].fill( base16.charAt( cursorColour ) ); + backgroundColour[y].fill( base16.charAt( cursorBackgroundColour ) ); + } + setChanged(); + } + public synchronized void clearLine() { - int y = this.m_cursorY; - if( y >= 0 && y < this.m_height ) + int y = cursorY; + if( y >= 0 && y < height ) { - this.m_text[y].fill( ' ' ); - this.m_textColour[y].fill( base16.charAt( this.m_cursorColour ) ); - this.m_backgroundColour[y].fill( base16.charAt( this.m_cursorBackgroundColour ) ); - this.setChanged(); + text[y].fill( ' ' ); + textColour[y].fill( base16.charAt( cursorColour ) ); + backgroundColour[y].fill( base16.charAt( cursorBackgroundColour ) ); + setChanged(); } } public synchronized TextBuffer getLine( int y ) { - if( y >= 0 && y < this.m_height ) + if( y >= 0 && y < height ) { - return this.m_text[y]; + return text[y]; } return null; } public synchronized void setLine( int y, String text, String textColour, String backgroundColour ) { - this.m_text[y].write( text ); - this.m_textColour[y].write( textColour ); - this.m_backgroundColour[y].write( backgroundColour ); - this.setChanged(); + this.text[y].write( text ); + this.textColour[y].write( textColour ); + this.backgroundColour[y].write( backgroundColour ); + setChanged(); } public synchronized TextBuffer getTextColourLine( int y ) { - if( y >= 0 && y < this.m_height ) + if( y >= 0 && y < height ) { - return this.m_textColour[y]; + return textColour[y]; } return null; } public synchronized TextBuffer getBackgroundColourLine( int y ) { - if( y >= 0 && y < this.m_height ) + if( y >= 0 && y < height ) { - return this.m_backgroundColour[y]; + return backgroundColour[y]; } return null; } + public final void setChanged() + { + if( onChanged != null ) onChanged.run(); + } + public synchronized void write( PacketByteBuf buffer ) { - buffer.writeInt( this.m_cursorX ); - buffer.writeInt( this.m_cursorY ); - buffer.writeBoolean( this.m_cursorBlink ); - buffer.writeByte( this.m_cursorBackgroundColour << 4 | this.m_cursorColour ); + buffer.writeInt( cursorX ); + buffer.writeInt( cursorY ); + buffer.writeBoolean( cursorBlink ); + buffer.writeByte( cursorBackgroundColour << 4 | cursorColour ); - for( int y = 0; y < this.m_height; y++ ) + for( int y = 0; y < height; y++ ) { - TextBuffer text = this.m_text[y]; - TextBuffer textColour = this.m_textColour[y]; - TextBuffer backColour = this.m_backgroundColour[y]; + TextBuffer text = this.text[y]; + TextBuffer textColour = this.textColour[y]; + TextBuffer backColour = backgroundColour[y]; - for( int x = 0; x < this.m_width; x++ ) + for( int x = 0; x < width; x++ ) { buffer.writeByte( text.charAt( x ) & 0xFF ); - buffer.writeByte( getColour( backColour.charAt( x ), Colour.BLACK ) << 4 | getColour( textColour.charAt( x ), Colour.WHITE ) ); + buffer.writeByte( getColour( + backColour.charAt( x ), Colour.BLACK ) << 4 | + getColour( textColour.charAt( x ), Colour.WHITE ) + ); } } - this.m_palette.write( buffer ); - } - - public static int getColour( char c, Colour def ) - { - if( c >= '0' && c <= '9' ) - { - return c - '0'; - } - if( c >= 'a' && c <= 'f' ) - { - return c - 'a' + 10; - } - return 15 - def.ordinal(); + palette.write( buffer ); } public synchronized void read( PacketByteBuf buffer ) { - this.m_cursorX = buffer.readInt(); - this.m_cursorY = buffer.readInt(); - this.m_cursorBlink = buffer.readBoolean(); + cursorX = buffer.readInt(); + cursorY = buffer.readInt(); + cursorBlink = buffer.readBoolean(); byte cursorColour = buffer.readByte(); - this.m_cursorBackgroundColour = (cursorColour >> 4) & 0xF; - this.m_cursorColour = cursorColour & 0xF; + cursorBackgroundColour = (cursorColour >> 4) & 0xF; + this.cursorColour = cursorColour & 0xF; - for( int y = 0; y < this.m_height; y++ ) + for( int y = 0; y < height; y++ ) { - TextBuffer text = this.m_text[y]; - TextBuffer textColour = this.m_textColour[y]; - TextBuffer backColour = this.m_backgroundColour[y]; + TextBuffer text = this.text[y]; + TextBuffer textColour = this.textColour[y]; + TextBuffer backColour = backgroundColour[y]; - for( int x = 0; x < this.m_width; x++ ) + for( int x = 0; x < width; x++ ) { text.setChar( x, (char) (buffer.readByte() & 0xFF) ); @@ -371,56 +362,63 @@ public class Terminal } } - this.m_palette.read( buffer ); - this.setChanged(); + palette.read( buffer ); + setChanged(); } public synchronized CompoundTag writeToNBT( CompoundTag nbt ) { - nbt.putInt( "term_cursorX", this.m_cursorX ); - nbt.putInt( "term_cursorY", this.m_cursorY ); - nbt.putBoolean( "term_cursorBlink", this.m_cursorBlink ); - nbt.putInt( "term_textColour", this.m_cursorColour ); - nbt.putInt( "term_bgColour", this.m_cursorBackgroundColour ); - for( int n = 0; n < this.m_height; n++ ) + nbt.putInt( "term_cursorX", cursorX ); + nbt.putInt( "term_cursorY", cursorY ); + nbt.putBoolean( "term_cursorBlink", cursorBlink ); + nbt.putInt( "term_textColour", cursorColour ); + nbt.putInt( "term_bgColour", cursorBackgroundColour ); + for( int n = 0; n < height; n++ ) { - nbt.putString( "term_text_" + n, this.m_text[n].toString() ); - nbt.putString( "term_textColour_" + n, this.m_textColour[n].toString() ); - nbt.putString( "term_textBgColour_" + n, this.m_backgroundColour[n].toString() ); + nbt.putString( "term_text_" + n, text[n].toString() ); + nbt.putString( "term_textColour_" + n, textColour[n].toString() ); + nbt.putString( "term_textBgColour_" + n, backgroundColour[n].toString() ); } - this.m_palette.writeToNBT( nbt ); + palette.writeToNBT( nbt ); return nbt; } public synchronized void readFromNBT( CompoundTag nbt ) { - this.m_cursorX = nbt.getInt( "term_cursorX" ); - this.m_cursorY = nbt.getInt( "term_cursorY" ); - this.m_cursorBlink = nbt.getBoolean( "term_cursorBlink" ); - this.m_cursorColour = nbt.getInt( "term_textColour" ); - this.m_cursorBackgroundColour = nbt.getInt( "term_bgColour" ); + cursorX = nbt.getInt( "term_cursorX" ); + cursorY = nbt.getInt( "term_cursorY" ); + cursorBlink = nbt.getBoolean( "term_cursorBlink" ); + cursorColour = nbt.getInt( "term_textColour" ); + cursorBackgroundColour = nbt.getInt( "term_bgColour" ); - for( int n = 0; n < this.m_height; n++ ) + for( int n = 0; n < height; n++ ) { - this.m_text[n].fill( ' ' ); + text[n].fill( ' ' ); if( nbt.contains( "term_text_" + n ) ) { - this.m_text[n].write( nbt.getString( "term_text_" + n ) ); + text[n].write( nbt.getString( "term_text_" + n ) ); } - this.m_textColour[n].fill( base16.charAt( this.m_cursorColour ) ); + textColour[n].fill( base16.charAt( cursorColour ) ); if( nbt.contains( "term_textColour_" + n ) ) { - this.m_textColour[n].write( nbt.getString( "term_textColour_" + n ) ); + textColour[n].write( nbt.getString( "term_textColour_" + n ) ); } - this.m_backgroundColour[n].fill( base16.charAt( this.m_cursorBackgroundColour ) ); + backgroundColour[n].fill( base16.charAt( cursorBackgroundColour ) ); if( nbt.contains( "term_textBgColour_" + n ) ) { - this.m_backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) ); + backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) ); } } - this.m_palette.readFromNBT( nbt ); - this.setChanged(); + palette.readFromNBT( nbt ); + setChanged(); + } + + public static int getColour( char c, Colour def ) + { + if( c >= '0' && c <= '9' ) return c - '0'; + if( c >= 'a' && c <= 'f' ) return c - 'a' + 10; + return 15 - def.ordinal(); } } diff --git a/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java b/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java index 44d5bcd2c..d042a2b34 100644 --- a/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java +++ b/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java @@ -83,4 +83,4 @@ public class TextBuffer { return new String( text ); } -} \ No newline at end of file +} diff --git a/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java b/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java index 0fbb848a2..0bc7787ca 100644 --- a/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java +++ b/src/main/java/dan200/computercraft/core/tracking/ComputerTracker.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.tracking; import dan200.computercraft.core.computer.Computer; @@ -16,126 +15,108 @@ public class ComputerTracker { private final WeakReference computer; private final int computerId; - private final Object2LongOpenHashMap fields; + private long tasks; private long totalTime; private long maxTime; + private long serverCount; private long serverTime; + private final Object2LongOpenHashMap fields; + public ComputerTracker( Computer computer ) { this.computer = new WeakReference<>( computer ); - this.computerId = computer.getID(); - this.fields = new Object2LongOpenHashMap<>(); + computerId = computer.getID(); + fields = new Object2LongOpenHashMap<>(); } ComputerTracker( ComputerTracker timings ) { - this.computer = timings.computer; - this.computerId = timings.computerId; + computer = timings.computer; + computerId = timings.computerId; - this.tasks = timings.tasks; - this.totalTime = timings.totalTime; - this.maxTime = timings.maxTime; + tasks = timings.tasks; + totalTime = timings.totalTime; + maxTime = timings.maxTime; - this.serverCount = timings.serverCount; - this.serverTime = timings.serverTime; + serverCount = timings.serverCount; + serverTime = timings.serverTime; - this.fields = new Object2LongOpenHashMap<>( timings.fields ); + fields = new Object2LongOpenHashMap<>( timings.fields ); } @Nullable public Computer getComputer() { - return this.computer.get(); + return computer.get(); } public int getComputerId() { - return this.computerId; + return computerId; } public long getTasks() { - return this.tasks; + return tasks; } public long getTotalTime() { - return this.totalTime; + return totalTime; } public long getMaxTime() { - return this.maxTime; + return maxTime; } public long getAverage() { - return this.totalTime / this.tasks; + return totalTime / tasks; } void addTaskTiming( long time ) { - this.tasks++; - this.totalTime += time; - if( time > this.maxTime ) - { - this.maxTime = time; - } + tasks++; + totalTime += time; + if( time > maxTime ) maxTime = time; } void addMainTiming( long time ) { - this.serverCount++; - this.serverTime += time; + serverCount++; + serverTime += time; } void addValue( TrackingField field, long change ) { - synchronized( this.fields ) + synchronized( fields ) { - this.fields.addTo( field, change ); + fields.addTo( field, change ); + } + } + + public long get( TrackingField field ) + { + if( field == TrackingField.TASKS ) return tasks; + if( field == TrackingField.MAX_TIME ) return maxTime; + if( field == TrackingField.TOTAL_TIME ) return totalTime; + if( field == TrackingField.AVERAGE_TIME ) return tasks == 0 ? 0 : totalTime / tasks; + + if( field == TrackingField.SERVER_COUNT ) return serverCount; + if( field == TrackingField.SERVER_TIME ) return serverTime; + + synchronized( fields ) + { + return fields.getLong( field ); } } public String getFormatted( TrackingField field ) { - return field.format( this.get( field ) ); - } - - public long get( TrackingField field ) - { - if( field == TrackingField.TASKS ) - { - return this.tasks; - } - if( field == TrackingField.MAX_TIME ) - { - return this.maxTime; - } - if( field == TrackingField.TOTAL_TIME ) - { - return this.totalTime; - } - if( field == TrackingField.AVERAGE_TIME ) - { - return this.tasks == 0 ? 0 : this.totalTime / this.tasks; - } - - if( field == TrackingField.SERVER_COUNT ) - { - return this.serverCount; - } - if( field == TrackingField.SERVER_TIME ) - { - return this.serverTime; - } - - synchronized( this.fields ) - { - return this.fields.getLong( field ); - } + return field.format( get( field ) ); } } diff --git a/src/main/java/dan200/computercraft/core/tracking/Tracker.java b/src/main/java/dan200/computercraft/core/tracking/Tracker.java index fd9220c9e..979f5863f 100644 --- a/src/main/java/dan200/computercraft/core/tracking/Tracker.java +++ b/src/main/java/dan200/computercraft/core/tracking/Tracker.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.tracking; import dan200.computercraft.core.computer.Computer; @@ -35,8 +34,8 @@ public interface Tracker } /** - * Increment an arbitrary field by some value. Implementations may track how often this is called as well as the change, to compute some level of - * "average". + * Increment an arbitrary field by some value. Implementations may track how often this is called + * as well as the change, to compute some level of "average". * * @param computer The computer to increment * @param field The field to increment. diff --git a/src/main/java/dan200/computercraft/core/tracking/Tracking.java b/src/main/java/dan200/computercraft/core/tracking/Tracking.java index 01347f294..1097e7d8a 100644 --- a/src/main/java/dan200/computercraft/core/tracking/Tracking.java +++ b/src/main/java/dan200/computercraft/core/tracking/Tracking.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.tracking; import dan200.computercraft.core.computer.Computer; @@ -29,10 +28,7 @@ public final class Tracking synchronized( lock ) { TrackingContext context = contexts.get( uuid ); - if( context == null ) - { - contexts.put( uuid, context = new TrackingContext() ); - } + if( context == null ) contexts.put( uuid, context = new TrackingContext() ); return context; } } @@ -48,61 +44,34 @@ public final class Tracking public static void addTaskTiming( Computer computer, long time ) { - if( tracking.get() == 0 ) - { - return; - } + if( tracking.get() == 0 ) return; synchronized( contexts ) { - for( TrackingContext context : contexts.values() ) - { - context.addTaskTiming( computer, time ); - } - for( Tracker tracker : trackers ) - { - tracker.addTaskTiming( computer, time ); - } + for( TrackingContext context : contexts.values() ) context.addTaskTiming( computer, time ); + for( Tracker tracker : trackers ) tracker.addTaskTiming( computer, time ); } } public static void addServerTiming( Computer computer, long time ) { - if( tracking.get() == 0 ) - { - return; - } + if( tracking.get() == 0 ) return; synchronized( contexts ) { - for( TrackingContext context : contexts.values() ) - { - context.addServerTiming( computer, time ); - } - for( Tracker tracker : trackers ) - { - tracker.addServerTiming( computer, time ); - } + for( TrackingContext context : contexts.values() ) context.addServerTiming( computer, time ); + for( Tracker tracker : trackers ) tracker.addServerTiming( computer, time ); } } public static void addValue( Computer computer, TrackingField field, long change ) { - if( tracking.get() == 0 ) - { - return; - } + if( tracking.get() == 0 ) return; synchronized( lock ) { - for( TrackingContext context : contexts.values() ) - { - context.addValue( computer, field, change ); - } - for( Tracker tracker : trackers ) - { - tracker.addValue( computer, field, change ); - } + for( TrackingContext context : contexts.values() ) context.addValue( computer, field, change ); + for( Tracker tracker : trackers ) tracker.addValue( computer, field, change ); } } diff --git a/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java b/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java index 24d448061..95621da4d 100644 --- a/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java +++ b/src/main/java/dan200/computercraft/core/tracking/TrackingContext.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.tracking; import com.google.common.collect.MapMaker; @@ -14,73 +13,63 @@ import java.util.List; import java.util.Map; /** - * Tracks timing information about computers, including how long they ran for and the number of events they handled. + * Tracks timing information about computers, including how long they ran for + * and the number of events they handled. * - * Note that this will track computers which have been deleted (hence the presence of {@link #timingLookup} and {@link #timings} + * Note that this will track computers which have been deleted (hence + * the presence of {@link #timingLookup} and {@link #timings} */ public class TrackingContext implements Tracker { - private final List timings = new ArrayList<>(); - private final Map timingLookup = new MapMaker().weakKeys() - .makeMap(); private boolean tracking = false; + private final List timings = new ArrayList<>(); + private final Map timingLookup = new MapMaker().weakKeys().makeMap(); + public synchronized void start() { - if( !this.tracking ) - { - Tracking.tracking.incrementAndGet(); - } - this.tracking = true; + if( !tracking ) Tracking.tracking.incrementAndGet(); + tracking = true; - this.timings.clear(); - this.timingLookup.clear(); + timings.clear(); + timingLookup.clear(); } public synchronized boolean stop() { - if( !this.tracking ) - { - return false; - } + if( !tracking ) return false; Tracking.tracking.decrementAndGet(); - this.tracking = false; - this.timingLookup.clear(); + tracking = false; + timingLookup.clear(); return true; } public synchronized List getImmutableTimings() { ArrayList timings = new ArrayList<>( this.timings.size() ); - for( ComputerTracker timing : this.timings ) - { - timings.add( new ComputerTracker( timing ) ); - } + for( ComputerTracker timing : this.timings ) timings.add( new ComputerTracker( timing ) ); return timings; } public synchronized List getTimings() { - return new ArrayList<>( this.timings ); + return new ArrayList<>( timings ); } @Override public void addTaskTiming( Computer computer, long time ) { - if( !this.tracking ) - { - return; - } + if( !tracking ) return; synchronized( this ) { - ComputerTracker computerTimings = this.timingLookup.get( computer ); + ComputerTracker computerTimings = timingLookup.get( computer ); if( computerTimings == null ) { computerTimings = new ComputerTracker( computer ); - this.timingLookup.put( computer, computerTimings ); - this.timings.add( computerTimings ); + timingLookup.put( computer, computerTimings ); + timings.add( computerTimings ); } computerTimings.addTaskTiming( time ); @@ -90,19 +79,16 @@ public class TrackingContext implements Tracker @Override public void addServerTiming( Computer computer, long time ) { - if( !this.tracking ) - { - return; - } + if( !tracking ) return; synchronized( this ) { - ComputerTracker computerTimings = this.timingLookup.get( computer ); + ComputerTracker computerTimings = timingLookup.get( computer ); if( computerTimings == null ) { computerTimings = new ComputerTracker( computer ); - this.timingLookup.put( computer, computerTimings ); - this.timings.add( computerTimings ); + timingLookup.put( computer, computerTimings ); + timings.add( computerTimings ); } computerTimings.addMainTiming( time ); @@ -112,19 +98,16 @@ public class TrackingContext implements Tracker @Override public void addValue( Computer computer, TrackingField field, long change ) { - if( !this.tracking ) - { - return; - } + if( !tracking ) return; synchronized( this ) { - ComputerTracker computerTimings = this.timingLookup.get( computer ); + ComputerTracker computerTimings = timingLookup.get( computer ); if( computerTimings == null ) { computerTimings = new ComputerTracker( computer ); - this.timingLookup.put( computer, computerTimings ); - this.timings.add( computerTimings ); + timingLookup.put( computer, computerTimings ); + timings.add( computerTimings ); } computerTimings.addValue( field, change ); diff --git a/src/main/java/dan200/computercraft/core/tracking/TrackingField.java b/src/main/java/dan200/computercraft/core/tracking/TrackingField.java index 2ffd29d78..c8e13f479 100644 --- a/src/main/java/dan200/computercraft/core/tracking/TrackingField.java +++ b/src/main/java/dan200/computercraft/core/tracking/TrackingField.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.tracking; import java.util.Collections; @@ -28,28 +27,41 @@ public final class TrackingField public static final TrackingField TURTLE_OPS = TrackingField.of( "turtle", TrackingField::formatDefault ); public static final TrackingField HTTP_REQUESTS = TrackingField.of( "http", TrackingField::formatDefault ); - public static final TrackingField COROUTINES_CREATED = TrackingField.of( "coroutines_created", x -> String.format( "%4d", x ) ); - public static final TrackingField COROUTINES_DISPOSED = TrackingField.of( "coroutines_dead", x -> String.format( "%4d", x ) ); - /** - * So technically a kibibyte, but let's not argue here. - */ - private static final int KILOBYTE_SIZE = 1024; - private static final String SI_PREFIXES = "KMGT"; public static final TrackingField HTTP_UPLOAD = TrackingField.of( "http_upload", TrackingField::formatBytes ); public static final TrackingField HTTP_DOWNLOAD = TrackingField.of( "http_download", TrackingField::formatBytes ); + public static final TrackingField WEBSOCKET_INCOMING = TrackingField.of( "websocket_incoming", TrackingField::formatBytes ); public static final TrackingField WEBSOCKET_OUTGOING = TrackingField.of( "websocket_outgoing", TrackingField::formatBytes ); + + public static final TrackingField COROUTINES_CREATED = TrackingField.of( "coroutines_created", x -> String.format( "%4d", x ) ); + public static final TrackingField COROUTINES_DISPOSED = TrackingField.of( "coroutines_dead", x -> String.format( "%4d", x ) ); + private final String id; private final String translationKey; private final LongFunction format; + public String id() + { + return id; + } + + public String translationKey() + { + return translationKey; + } + private TrackingField( String id, LongFunction format ) { this.id = id; - this.translationKey = "tracking_field.computercraft." + id + ".name"; + translationKey = "tracking_field.computercraft." + id + ".name"; this.format = format; } + public String format( long value ) + { + return format.apply( value ); + } + public static TrackingField of( String id, LongFunction format ) { TrackingField field = new TrackingField( id, format ); @@ -67,32 +79,18 @@ public final class TrackingField return String.format( "%6d", value ); } + /** + * So technically a kibibyte, but let's not argue here. + */ + private static final int KILOBYTE_SIZE = 1024; + + private static final String SI_PREFIXES = "KMGT"; + private static String formatBytes( long bytes ) { - if( bytes < 1024 ) - { - return String.format( "%10d B", bytes ); - } + if( bytes < 1024 ) return String.format( "%10d B", bytes ); int exp = (int) (Math.log( bytes ) / Math.log( KILOBYTE_SIZE )); - if( exp > SI_PREFIXES.length() ) - { - exp = SI_PREFIXES.length(); - } + if( exp > SI_PREFIXES.length() ) exp = SI_PREFIXES.length(); return String.format( "%10.1f %siB", bytes / Math.pow( KILOBYTE_SIZE, exp ), SI_PREFIXES.charAt( exp - 1 ) ); } - - public String id() - { - return this.id; - } - - public String translationKey() - { - return this.translationKey; - } - - public String format( long value ) - { - return this.format.apply( value ); - } } diff --git a/src/main/java/dan200/computercraft/shared/util/Config.java b/src/main/java/dan200/computercraft/shared/util/Config.java index b9fc34156..fdf35bd77 100644 --- a/src/main/java/dan200/computercraft/shared/util/Config.java +++ b/src/main/java/dan200/computercraft/shared/util/Config.java @@ -5,10 +5,7 @@ */ package dan200.computercraft.shared.util; -import com.electronwill.nightconfig.core.CommentedConfig; -import com.electronwill.nightconfig.core.ConfigSpec; -import com.electronwill.nightconfig.core.EnumGetMethod; -import com.electronwill.nightconfig.core.UnmodifiableConfig; +import com.electronwill.nightconfig.core.*; import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.electronwill.nightconfig.core.file.FileNotFoundAction; import com.google.common.base.CaseFormat; @@ -30,8 +27,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -public class Config -{ +public class Config { private static final int MODEM_MAX_RANGE = 100000; public static final String TRANSLATION_PREFIX = "gui.computercraft.config."; @@ -42,346 +38,327 @@ public class Config public static CommentedConfig serverConfig; public static CommentedConfig clientConfig; - private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath( "serverconfig" ); + private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath("serverconfig"); private static final String serverFileName = "computercraft-server.toml"; - private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve( "computercraft-client.toml" ); + private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve("computercraft-client.toml"); - private Config() - { + private Config() { } - static - { - System.setProperty( "nightconfig.preserveInsertionOrder", "true" ); + static { + System.setProperty("nightconfig.preserveInsertionOrder", "true"); serverSpec = new CommentedConfigSpec(); { // General computers - serverSpec.comment( "computer_space_limit", - "The disk space limit for computers and turtles, in bytes" ); - serverSpec.define( "computer_space_limit", ComputerCraft.computerSpaceLimit ); + serverSpec.comment("computer_space_limit", + "The disk space limit for computers and turtles, in bytes"); + serverSpec.define("computer_space_limit", ComputerCraft.computerSpaceLimit); - serverSpec.comment( "floppy_space_limit", - "The disk space limit for floppy disks, in bytes" ); - serverSpec.define( "floppy_space_limit", ComputerCraft.floppySpaceLimit ); + serverSpec.comment("floppy_space_limit", + "The disk space limit for floppy disks, in bytes"); + serverSpec.define("floppy_space_limit", ComputerCraft.floppySpaceLimit); - serverSpec.comment( "maximum_open_files", - "Set how many files a computer can have open at the same time. Set to 0 for unlimited." ); - serverSpec.defineInRange( "maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE ); + serverSpec.comment("maximum_open_files", + "Set how many files a computer can have open at the same time. Set to 0 for unlimited."); + serverSpec.defineInRange("maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE); - serverSpec.comment( "disable_lua51_features", - "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + - "Useful for ensuring forward compatibility of your programs now." ); - serverSpec.define( "disable_lua51_features", ComputerCraft.disableLua51Features ); + serverSpec.comment("disable_lua51_features", + "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + + "Useful for ensuring forward compatibility of your programs now."); + serverSpec.define("disable_lua51_features", ComputerCraft.disableLua51Features); - serverSpec.comment( "default_computer_settings", - "A comma separated list of default system settings to set on new computers. Example: " + + serverSpec.comment("default_computer_settings", + "A comma separated list of default system settings to set on new computers. Example: " + "\"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all " + - "autocompletion" ); - serverSpec.define( "default_computer_settings", ComputerCraft.defaultComputerSettings ); + "autocompletion"); + serverSpec.define("default_computer_settings", ComputerCraft.defaultComputerSettings); - serverSpec.comment( "debug_enabled", - "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players." ); - serverSpec.define( "debug_enabled", ComputerCraft.debugEnable ); + serverSpec.comment("debug_enabled", + "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players."); + serverSpec.define("debug_enabled", ComputerCraft.debugEnable); - serverSpec.comment( "log_computer_errors", - "Log exceptions thrown by peripherals and other Lua objects.\n" + - "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods." ); - serverSpec.define( "log_computer_errors", ComputerCraft.logComputerErrors ); + serverSpec.comment("log_computer_errors", + "Log exceptions thrown by peripherals and other Lua objects.\n" + + "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods."); + serverSpec.define("log_computer_errors", ComputerCraft.logComputerErrors); - serverSpec.comment( "command_require_creative", - "Require players to be in creative mode and be opped in order to interact with command computers." + - "This is the default behaviour for vanilla's Command blocks." ); - serverSpec.define( "command_require_creative", ComputerCraft.commandRequireCreative ); + serverSpec.comment("command_require_creative", + "Require players to be in creative mode and be opped in order to interact with command computers." + + "This is the default behaviour for vanilla's Command blocks."); + serverSpec.define("command_require_creative", ComputerCraft.commandRequireCreative); } { // Execution - serverSpec.comment( "execution", - "Controls execution behaviour of computers. This is largely intended for fine-tuning " + - "servers, and generally shouldn't need to be touched" ); + serverSpec.comment("execution", + "Controls execution behaviour of computers. This is largely intended for fine-tuning " + + "servers, and generally shouldn't need to be touched"); - serverSpec.comment( "execution.computer_threads", - "Set the number of threads computers can run on. A higher number means more computers can run " + + serverSpec.comment("execution.computer_threads", + "Set the number of threads computers can run on. A higher number means more computers can run " + "at once, but may induce lag.\n" + - "Please note that some mods may not work with a thread count higher than 1. Use with caution." ); - serverSpec.defineInRange( "execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE ); + "Please note that some mods may not work with a thread count higher than 1. Use with caution."); + serverSpec.defineInRange("execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE); - serverSpec.comment( "execution.max_main_global_time", - "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + + serverSpec.comment("execution.max_main_global_time", + "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time." ); - serverSpec.defineInRange( "execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE ); + "- this aims to be the upper bound of the average time."); + serverSpec.defineInRange("execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE); - serverSpec.comment( "execution.max_main_computer_time", - "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + + serverSpec.comment("execution.max_main_computer_time", + "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time." ); - serverSpec.defineInRange( "execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE ); + "- this aims to be the upper bound of the average time."); + serverSpec.defineInRange("execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE); } { // HTTP - serverSpec.comment( "http", "Controls the HTTP API" ); + serverSpec.comment("http", "Controls the HTTP API"); - serverSpec.comment( "http.enabled", - "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)." ); - serverSpec.define( "http.enabled", ComputerCraft.httpEnabled ); + serverSpec.comment("http.enabled", + "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)."); + serverSpec.define("http.enabled", ComputerCraft.httpEnabled); - serverSpec.comment( "http.websocket_enabled", - "Enable use of http websockets. This requires the \"http_enable\" option to also be true." ); - serverSpec.define( "http.websocket_enabled", ComputerCraft.httpWebsocketEnabled ); + serverSpec.comment("http.websocket_enabled", + "Enable use of http websockets. This requires the \"http_enable\" option to also be true."); + serverSpec.define("http.websocket_enabled", ComputerCraft.httpWebsocketEnabled); - serverSpec.comment( "http.rules", - "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + + serverSpec.comment("http.rules", + "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + "Each rule is an item with a 'host' to match against, and a series of properties. " + "The host may be a domain name (\"pastebin.com\"),\n" + - "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked." ); - serverSpec.defineList( "http.rules", Arrays.asList( - AddressRuleConfig.makeRule( "$private", Action.DENY ), - AddressRuleConfig.makeRule( "*", Action.ALLOW ) - ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule( (UnmodifiableConfig) x ) ); + "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked."); + serverSpec.defineList("http.rules", Arrays.asList( + AddressRuleConfig.makeRule("$private", Action.DENY), + AddressRuleConfig.makeRule("*", Action.ALLOW) + ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule((UnmodifiableConfig) x)); - serverSpec.comment( "http.max_requests", - "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited." ); - serverSpec.defineInRange( "http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE ); + serverSpec.comment("http.max_requests", + "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited."); + serverSpec.defineInRange("http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE); - serverSpec.comment( "http.max_websockets", - "The number of websockets a computer can have open at one time. Set to 0 for unlimited." ); - serverSpec.defineInRange( "http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE ); + serverSpec.comment("http.max_websockets", + "The number of websockets a computer can have open at one time. Set to 0 for unlimited."); + serverSpec.defineInRange("http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE); } { // Peripherals - serverSpec.comment( "peripheral", "Various options relating to peripherals." ); + serverSpec.comment("peripheral", "Various options relating to peripherals."); - serverSpec.comment( "peripheral.command_block_enabled", - "Enable Command Block peripheral support" ); - serverSpec.define( "peripheral.command_block_enabled", ComputerCraft.enableCommandBlock ); + serverSpec.comment("peripheral.command_block_enabled", + "Enable Command Block peripheral support"); + serverSpec.define("peripheral.command_block_enabled", ComputerCraft.enableCommandBlock); - serverSpec.comment( "peripheral.modem_range", - "The range of Wireless Modems at low altitude in clear weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE ); + serverSpec.comment("peripheral.modem_range", + "The range of Wireless Modems at low altitude in clear weather, in meters"); + serverSpec.defineInRange("peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE); - serverSpec.comment( "peripheral.modem_high_altitude_range", - "The range of Wireless Modems at maximum altitude in clear weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE ); + serverSpec.comment("peripheral.modem_high_altitude_range", + "The range of Wireless Modems at maximum altitude in clear weather, in meters"); + serverSpec.defineInRange("peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE); - serverSpec.comment( "peripheral.modem_range_during_storm", - "The range of Wireless Modems at low altitude in stormy weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE ); + serverSpec.comment("peripheral.modem_range_during_storm", + "The range of Wireless Modems at low altitude in stormy weather, in meters"); + serverSpec.defineInRange("peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE); - serverSpec.comment( "peripheral.modem_high_altitude_range_during_storm", - "The range of Wireless Modems at maximum altitude in stormy weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE ); + serverSpec.comment("peripheral.modem_high_altitude_range_during_storm", + "The range of Wireless Modems at maximum altitude in stormy weather, in meters"); + serverSpec.defineInRange("peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE); - serverSpec.comment( "peripheral.max_notes_per_tick", - "Maximum amount of notes a speaker can play at once" ); - serverSpec.defineInRange( "peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE ); + serverSpec.comment("peripheral.max_notes_per_tick", + "Maximum amount of notes a speaker can play at once"); + serverSpec.defineInRange("peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE); - serverSpec.comment( "peripheral.monitor_bandwidth", - "The limit to how much monitor data can be sent *per tick*. Note:\n" + + serverSpec.comment("peripheral.monitor_bandwidth", + "The limit to how much monitor data can be sent *per tick*. Note:\n" + " - Bandwidth is measured before compression, so the data sent to the client is smaller.\n" + " - This ignores the number of players a packet is sent to. Updating a monitor for one player consumes " + "the same bandwidth limit as sending to 20.\n" + " - A full sized monitor sends ~25kb of data. So the default (1MB) allows for ~40 monitors to be updated " + "in a single tick. \n" + - "Set to 0 to disable." ); - serverSpec.defineInRange( "peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE ); + "Set to 0 to disable."); + serverSpec.defineInRange("peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE); } { // Turtles - serverSpec.comment( "turtle", "Various options relating to turtles." ); + serverSpec.comment("turtle", "Various options relating to turtles."); - serverSpec.comment( "turtle.need_fuel", - "Set whether Turtles require fuel to move" ); - serverSpec.define( "turtle.need_fuel", ComputerCraft.turtlesNeedFuel ); + serverSpec.comment("turtle.need_fuel", + "Set whether Turtles require fuel to move"); + serverSpec.define("turtle.need_fuel", ComputerCraft.turtlesNeedFuel); - serverSpec.comment( "turtle.normal_fuel_limit", "The fuel limit for Turtles" ); - serverSpec.defineInRange( "turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE ); + serverSpec.comment("turtle.normal_fuel_limit", "The fuel limit for Turtles"); + serverSpec.defineInRange("turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE); - serverSpec.comment( "turtle.advanced_fuel_limit", - "The fuel limit for Advanced Turtles" ); - serverSpec.defineInRange( "turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE ); + serverSpec.comment("turtle.advanced_fuel_limit", + "The fuel limit for Advanced Turtles"); + serverSpec.defineInRange("turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE); - serverSpec.comment( "turtle.obey_block_protection", - "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)" ); - serverSpec.define( "turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection ); + serverSpec.comment("turtle.obey_block_protection", + "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)"); + serverSpec.define("turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection); - serverSpec.comment( "turtle.can_push", - "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so" ); - serverSpec.define( "turtle.can_push", ComputerCraft.turtlesCanPush ); + serverSpec.comment("turtle.can_push", + "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so"); + serverSpec.define("turtle.can_push", ComputerCraft.turtlesCanPush); - serverSpec.comment( "turtle.disabled_actions", - "A list of turtle actions which are disabled." ); - serverSpec.defineList( "turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction( (String) x ) != null ); + serverSpec.comment("turtle.disabled_actions", + "A list of turtle actions which are disabled."); + serverSpec.defineList("turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction((String) x) != null); } { - serverSpec.comment( "term_sizes", "Configure the size of various computer's terminals.\n" + - "Larger terminals require more bandwidth, so use with care." ); + serverSpec.comment("term_sizes", "Configure the size of various computer's terminals.\n" + + "Larger terminals require more bandwidth, so use with care."); - serverSpec.comment( "term_sizes.computer", "Terminal size of computers" ); - serverSpec.defineInRange( "term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255 ); - serverSpec.defineInRange( "term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255 ); + serverSpec.comment("term_sizes.computer", "Terminal size of computers"); + serverSpec.defineInRange("term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255); + serverSpec.defineInRange("term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255); - serverSpec.comment( "term_sizes.pocket_computer", "Terminal size of pocket computers" ); - serverSpec.defineInRange( "term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255 ); - serverSpec.defineInRange( "term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255 ); + serverSpec.comment("term_sizes.pocket_computer", "Terminal size of pocket computers"); + serverSpec.defineInRange("term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255); + serverSpec.defineInRange("term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255); - serverSpec.comment( "term_sizes.monitor", "Maximum size of monitors (in blocks)" ); - serverSpec.defineInRange( "term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32 ); - serverSpec.defineInRange( "term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32 ); + serverSpec.comment("term_sizes.monitor", "Maximum size of monitors (in blocks)"); + serverSpec.defineInRange("term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32); + serverSpec.defineInRange("term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32); } clientSpec = new CommentedConfigSpec(); - clientSpec.comment( "monitor_renderer", - "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + - "monitors have performance issues, you may wish to experiment with alternative renderers." ); - clientSpec.defineRestrictedEnum( "monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf( MonitorRenderer.class ), EnumGetMethod.NAME_IGNORECASE ); + clientSpec.comment("monitor_renderer", + "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + + "monitors have performance issues, you may wish to experiment with alternative renderers."); + clientSpec.defineRestrictedEnum("monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf(MonitorRenderer.class), EnumGetMethod.NAME_IGNORECASE); - clientSpec.comment( "monitor_distance", - "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + + clientSpec.comment("monitor_distance", + "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + "but may be extended if you wish to build larger monitors." ); - clientSpec.defineInRange( "monitor_distance", 64, 16, 1024 ); + clientSpec.defineInRange("monitor_distance", 64, 16, 1024); } - private static final FileNotFoundAction MAKE_DIRECTORIES = ( file, configFormat ) -> { - Files.createDirectories( file.getParent() ); - Files.createFile( file ); - configFormat.initEmptyFile( file ); + private static final FileNotFoundAction MAKE_DIRECTORIES = (file, configFormat) -> { + Files.createDirectories(file.getParent()); + Files.createFile(file); + configFormat.initEmptyFile(file); return false; }; - private static CommentedFileConfig buildFileConfig( Path path ) - { - return CommentedFileConfig.builder( path ) - .onFileNotFound( MAKE_DIRECTORIES ) - .preserveInsertionOrder() - .build(); + private static CommentedFileConfig buildFileConfig(Path path) { + return CommentedFileConfig.builder(path) + .onFileNotFound(MAKE_DIRECTORIES) + .preserveInsertionOrder() + .build(); } - public static void serverStarting( MinecraftServer server ) - { - Path serverPath = server.getSavePath( serverDir ).resolve( serverFileName ); + public static void serverStarting(MinecraftServer server) { + Path serverPath = server.getSavePath(serverDir).resolve(serverFileName); - try( CommentedFileConfig config = buildFileConfig( serverPath ) ) - { + try(CommentedFileConfig config = buildFileConfig(serverPath)) { config.load(); - serverSpec.correct( config, Config::correctionListener ); + serverSpec.correct(config, Config::correctionListener); config.save(); serverConfig = config; sync(); } } - public static void serverStopping( MinecraftServer server ) - { + public static void serverStopping(MinecraftServer server) { serverConfig = null; } - public static void clientStarted( MinecraftClient client ) - { - try( CommentedFileConfig config = buildFileConfig( clientPath ) ) - { + public static void clientStarted(MinecraftClient client) { + try (CommentedFileConfig config = buildFileConfig(clientPath)) { config.load(); - clientSpec.correct( config, Config::correctionListener ); + clientSpec.correct(config, Config::correctionListener); config.save(); clientConfig = config; sync(); } } - private static void correctionListener( ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue ) - { - String key = String.join( ".", path ); - switch( action ) - { + private static void correctionListener(ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue) { + String key = String.join(".", path); + switch(action) { case ADD: - ComputerCraft.log.warn( "Config key {} missing -> added default value.", key ); - break; + ComputerCraft.log.warn("Config key {} missing -> added default value.", key); break; case REMOVE: - ComputerCraft.log.warn( "Config key {} not defined -> removed from config.", key ); - break; + ComputerCraft.log.warn("Config key {} not defined -> removed from config.", key); break; case REPLACE: - ComputerCraft.log.warn( "Config key {} not valid -> replaced with default value.", key ); + ComputerCraft.log.warn("Config key {} not valid -> replaced with default value.", key); } } - public static void sync() - { - if( serverConfig != null ) - { + public static void sync() { + if(serverConfig != null) { // General - ComputerCraft.computerSpaceLimit = serverConfig.get( "computer_space_limit" ); - ComputerCraft.floppySpaceLimit = serverConfig.get( "floppy_space_limit" ); - ComputerCraft.maximumFilesOpen = serverConfig.get( "maximum_open_files" ); - ComputerCraft.disableLua51Features = serverConfig.get( "disable_lua51_features" ); - ComputerCraft.defaultComputerSettings = serverConfig.get( "default_computer_settings" ); - ComputerCraft.debugEnable = serverConfig.get( "debug_enabled" ); - ComputerCraft.logComputerErrors = serverConfig.get( "log_computer_errors" ); - ComputerCraft.commandRequireCreative = serverConfig.get( "command_require_creative" ); + ComputerCraft.computerSpaceLimit = serverConfig.get("computer_space_limit"); + ComputerCraft.floppySpaceLimit = serverConfig.get("floppy_space_limit"); + ComputerCraft.maximumFilesOpen = serverConfig.get("maximum_open_files"); + ComputerCraft.disableLua51Features = serverConfig.get("disable_lua51_features"); + ComputerCraft.defaultComputerSettings = serverConfig.get("default_computer_settings"); + ComputerCraft.debugEnable = serverConfig.get("debug_enabled"); + ComputerCraft.logComputerErrors = serverConfig.get("log_computer_errors"); + ComputerCraft.commandRequireCreative = serverConfig.get("command_require_creative"); // Execution - ComputerCraft.computerThreads = serverConfig.get( "execution.computer_threads" ); - ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_global_time" ) ); - ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_computer_time" ) ); + ComputerCraft.computerThreads = serverConfig.get("execution.computer_threads"); + ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_global_time")); + ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_computer_time")); // HTTP - ComputerCraft.httpEnabled = serverConfig.get( "http.enabled" ); - ComputerCraft.httpWebsocketEnabled = serverConfig.get( "http.websocket_enabled" ); - ComputerCraft.httpRules = serverConfig.>get( "http.rules" ).stream().map( AddressRuleConfig::parseRule ) - .filter( Objects::nonNull ).collect( Collectors.toList() ); - ComputerCraft.httpMaxRequests = serverConfig.get( "http.max_requests" ); - ComputerCraft.httpMaxWebsockets = serverConfig.get( "http.max_websockets" ); + ComputerCraft.httpEnabled = serverConfig.get("http.enabled"); + ComputerCraft.httpWebsocketEnabled = serverConfig.get("http.websocket_enabled"); + ComputerCraft.httpRules = serverConfig.>get("http.rules").stream().map(AddressRuleConfig::parseRule) + .filter(Objects::nonNull).collect(Collectors.toList()); + ComputerCraft.httpMaxRequests = serverConfig.get("http.max_requests"); + ComputerCraft.httpMaxWebsockets = serverConfig.get("http.max_websockets"); // Peripherals - ComputerCraft.enableCommandBlock = serverConfig.get( "peripheral.command_block_enabled" ); - ComputerCraft.modemRange = serverConfig.get( "peripheral.modem_range" ); - ComputerCraft.modemHighAltitudeRange = serverConfig.get( "peripheral.modem_high_altitude_range" ); - ComputerCraft.modemRangeDuringStorm = serverConfig.get( "peripheral.modem_range_during_storm" ); - ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get( "peripheral.modem_high_altitude_range_during_storm" ); - ComputerCraft.maxNotesPerTick = serverConfig.get( "peripheral.max_notes_per_tick" ); - ComputerCraft.monitorBandwidth = serverConfig.get( "peripheral.monitor_bandwidth" ); + ComputerCraft.enableCommandBlock = serverConfig.get("peripheral.command_block_enabled"); + ComputerCraft.modemRange = serverConfig.get("peripheral.modem_range"); + ComputerCraft.modemHighAltitudeRange = serverConfig.get("peripheral.modem_high_altitude_range"); + ComputerCraft.modemRangeDuringStorm = serverConfig.get("peripheral.modem_range_during_storm"); + ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get("peripheral.modem_high_altitude_range_during_storm"); + ComputerCraft.maxNotesPerTick = serverConfig.get("peripheral.max_notes_per_tick"); + ComputerCraft.monitorBandwidth = serverConfig.get("peripheral.monitor_bandwidth"); // Turtles - ComputerCraft.turtlesNeedFuel = serverConfig.get( "turtle.need_fuel" ); - ComputerCraft.turtleFuelLimit = serverConfig.get( "turtle.normal_fuel_limit" ); - ComputerCraft.advancedTurtleFuelLimit = serverConfig.get( "turtle.advanced_fuel_limit" ); - ComputerCraft.turtlesObeyBlockProtection = serverConfig.get( "turtle.obey_block_protection" ); - ComputerCraft.turtlesCanPush = serverConfig.get( "turtle.can_push" ); + ComputerCraft.turtlesNeedFuel = serverConfig.get("turtle.need_fuel"); + ComputerCraft.turtleFuelLimit = serverConfig.get("turtle.normal_fuel_limit"); + ComputerCraft.advancedTurtleFuelLimit = serverConfig.get("turtle.advanced_fuel_limit"); + ComputerCraft.turtlesObeyBlockProtection = serverConfig.get("turtle.obey_block_protection"); + ComputerCraft.turtlesCanPush = serverConfig.get("turtle.can_push"); ComputerCraft.turtleDisabledActions.clear(); - for( String value : serverConfig.>get( "turtle.disabled_actions" ) ) - { - ComputerCraft.turtleDisabledActions.add( getAction( value ) ); + for(String value : serverConfig.>get("turtle.disabled_actions")) { + ComputerCraft.turtleDisabledActions.add(getAction(value)); } // Terminal Size - ComputerCraft.computerTermWidth = serverConfig.get( "term_sizes.computer.width" ); - ComputerCraft.computerTermHeight = serverConfig.get( "term_sizes.computer.height" ); - ComputerCraft.pocketTermWidth = serverConfig.get( "term_sizes.pocket_computer.width" ); - ComputerCraft.pocketTermHeight = serverConfig.get( "term_sizes.pocket_computer.height" ); - ComputerCraft.monitorWidth = serverConfig.get( "term_sizes.monitor.width" ); - ComputerCraft.monitorHeight = serverConfig.get( "term_sizes.monitor.height" ); + ComputerCraft.computerTermWidth = serverConfig.get("term_sizes.computer.width"); + ComputerCraft.computerTermHeight = serverConfig.get("term_sizes.computer.height"); + ComputerCraft.pocketTermWidth = serverConfig.get("term_sizes.pocket_computer.width"); + ComputerCraft.pocketTermHeight = serverConfig.get("term_sizes.pocket_computer.height"); + ComputerCraft.monitorWidth = serverConfig.get("term_sizes.monitor.width"); + ComputerCraft.monitorHeight = serverConfig.get("term_sizes.monitor.height"); } // Client - if( clientConfig != null ) - { - ComputerCraft.monitorRenderer = clientConfig.getEnum( "monitor_renderer", MonitorRenderer.class ); - int distance = clientConfig.get( "monitor_distance" ); + if(clientConfig != null) { + ComputerCraft.monitorRenderer = clientConfig.getEnum("monitor_renderer", MonitorRenderer.class); + int distance = clientConfig.get("monitor_distance"); ComputerCraft.monitorDistanceSq = distance * distance; } } - private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo( CaseFormat.UPPER_UNDERSCORE ); + private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE); - private static TurtleAction getAction( String value ) - { - try - { - return TurtleAction.valueOf( converter.convert( value ) ); + private static TurtleAction getAction(String value) { + try { + return TurtleAction.valueOf(converter.convert(value)); } - catch( IllegalArgumentException e ) - { + catch(IllegalArgumentException e) { return null; } } From 59266fe6e954bcd3c07a6a72f72dad28acc83daa Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 9 Jun 2021 08:55:11 +0100 Subject: [PATCH 5/8] No more m_ nice guy --- .../computercraft/client/gui/GuiPrintout.java | 48 +- .../computercraft/client/gui/GuiTurtle.java | 18 +- .../client/render/TurtleMultiModel.java | 66 +-- .../client/render/TurtleSmartItemModel.java | 62 +-- .../shared/common/ClientTerminal.java | 42 +- .../shared/common/ServerTerminal.java | 48 +- .../shared/computer/blocks/ComputerProxy.java | 6 +- .../computer/blocks/TileComputerBase.java | 78 ++-- .../shared/computer/core/ClientComputer.java | 44 +- .../computer/core/ComputerRegistry.java | 34 +- .../shared/computer/core/ServerComputer.java | 120 ++--- .../peripheral/diskdrive/TileDiskDrive.java | 136 +++--- .../peripheral/modem/ModemPeripheral.java | 62 +-- .../peripheral/modem/wired/TileCable.java | 102 ++--- .../modem/wired/TileWiredModemFull.java | 100 ++--- .../wireless/WirelessModemPeripheral.java | 8 +- .../modem/wireless/WirelessNetwork.java | 20 +- .../peripheral/monitor/TileMonitor.java | 272 +++++------ .../peripheral/printer/TilePrinter.java | 120 ++--- .../peripheral/speaker/SpeakerPeripheral.java | 18 +- .../pocket/core/PocketServerComputer.java | 50 +-- .../shared/turtle/blocks/TileTurtle.java | 116 ++--- .../shared/turtle/core/TurtleBrain.java | 254 +++++------ .../turtle/core/TurtleCompareCommand.java | 6 +- .../turtle/core/TurtleCompareToCommand.java | 6 +- .../turtle/core/TurtleDetectCommand.java | 6 +- .../shared/turtle/core/TurtleDropCommand.java | 14 +- .../turtle/core/TurtleEquipCommand.java | 8 +- .../shared/turtle/core/TurtleMoveCommand.java | 10 +- .../turtle/core/TurtlePlaceCommand.java | 12 +- .../shared/turtle/core/TurtlePlayer.java | 4 +- .../shared/turtle/core/TurtleSuckCommand.java | 18 +- .../turtle/core/TurtleTransferToCommand.java | 12 +- .../shared/turtle/core/TurtleTurnCommand.java | 6 +- .../turtle/upgrades/TurtleCraftingTable.java | 12 +- .../upgrades/TurtleInventoryCrafting.java | 46 +- .../shared/turtle/upgrades/TurtleModem.java | 28 +- .../shared/turtle/upgrades/TurtleSpeaker.java | 12 +- .../computercraft/shared/util/Config.java | 421 +++++++++--------- 39 files changed, 1234 insertions(+), 1211 deletions(-) diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java index c944aaed4..47833b321 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java @@ -25,11 +25,11 @@ import static dan200.computercraft.client.render.PrintoutRenderer.*; public class GuiPrintout extends HandledScreen { - private final boolean m_book; - private final int m_pages; - private final TextBuffer[] m_text; - private final TextBuffer[] m_colours; - private int m_page; + private final boolean book; + private final int pages; + private final TextBuffer[] text; + private final TextBuffer[] colours; + private int page; public GuiPrintout( ContainerHeldItem container, PlayerInventory player, Text title ) { @@ -38,22 +38,22 @@ public class GuiPrintout extends HandledScreen this.backgroundHeight = Y_SIZE; String[] text = ItemPrintout.getText( container.getStack() ); - this.m_text = new TextBuffer[text.length]; - for( int i = 0; i < this.m_text.length; i++ ) + this.text = new TextBuffer[text.length]; + for( int i = 0; i < this.text.length; i++ ) { - this.m_text[i] = new TextBuffer( text[i] ); + this.text[i] = new TextBuffer( text[i] ); } String[] colours = ItemPrintout.getColours( container.getStack() ); - this.m_colours = new TextBuffer[colours.length]; - for( int i = 0; i < this.m_colours.length; i++ ) + this.colours = new TextBuffer[colours.length]; + for( int i = 0; i < this.colours.length; i++ ) { - this.m_colours[i] = new TextBuffer( colours[i] ); + this.colours[i] = new TextBuffer( colours[i] ); } - this.m_page = 0; - this.m_pages = Math.max( this.m_text.length / ItemPrintout.LINES_PER_PAGE, 1 ); - this.m_book = ((ItemPrintout) container.getStack() + this.page = 0; + this.pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 ); + this.book = ((ItemPrintout) container.getStack() .getItem()).getType() == ItemPrintout.Type.BOOK; } @@ -67,9 +67,9 @@ public class GuiPrintout extends HandledScreen if( delta < 0 ) { // Scroll up goes to the next page - if( this.m_page < this.m_pages - 1 ) + if( this.page < this.pages - 1 ) { - this.m_page++; + this.page++; } return true; } @@ -77,9 +77,9 @@ public class GuiPrintout extends HandledScreen if( delta > 0 ) { // Scroll down goes to the previous page - if( this.m_page > 0 ) + if( this.page > 0 ) { - this.m_page--; + this.page--; } return true; } @@ -116,8 +116,8 @@ public class GuiPrintout extends HandledScreen .getEntityVertexConsumers(); Matrix4f matrix = transform.peek() .getModel(); - drawBorder( matrix, renderer, this.x, this.y, this.getZOffset(), this.m_page, this.m_pages, this.m_book ); - drawText( matrix, renderer, this.x + X_TEXT_MARGIN, this.y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * this.m_page, this.m_text, this.m_colours ); + drawBorder( matrix, renderer, this.x, this.y, this.getZOffset(), this.page, this.pages, this.book ); + drawText( matrix, renderer, this.x + X_TEXT_MARGIN, this.y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * this.page, this.text, this.colours ); renderer.draw(); } @@ -131,18 +131,18 @@ public class GuiPrintout extends HandledScreen if( key == GLFW.GLFW_KEY_RIGHT ) { - if( this.m_page < this.m_pages - 1 ) + if( this.page < this.pages - 1 ) { - this.m_page++; + this.page++; } return true; } if( key == GLFW.GLFW_KEY_LEFT ) { - if( this.m_page > 0 ) + if( this.page > 0 ) { - this.m_page--; + this.page--; } return true; } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java index 4a731ad2a..3bee58b7c 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java @@ -26,9 +26,9 @@ public class GuiTurtle extends HandledScreen { private static final Identifier BACKGROUND_NORMAL = new Identifier( "computercraft", "textures/gui/turtle_normal.png" ); private static final Identifier BACKGROUND_ADVANCED = new Identifier( "computercraft", "textures/gui/turtle_advanced.png" ); - private final ComputerFamily m_family; - private final ClientComputer m_computer; - private ContainerTurtle m_container; + private final ComputerFamily family; + private final ClientComputer computer; + private final ContainerTurtle container; private WidgetTerminal terminal; private WidgetWrapper terminalWrapper; @@ -36,9 +36,9 @@ public class GuiTurtle extends HandledScreen { super( container, player, title ); - this.m_container = container; - this.m_family = container.getFamily(); - this.m_computer = (ClientComputer) container.getComputer(); + this.container = container; + this.family = container.getFamily(); + this.computer = (ClientComputer) container.getComputer(); this.backgroundWidth = 254; this.backgroundHeight = 217; @@ -53,7 +53,7 @@ public class GuiTurtle extends HandledScreen int termPxWidth = ComputerCraft.turtleTermWidth * FixedWidthFontRenderer.FONT_WIDTH; int termPxHeight = ComputerCraft.turtleTermHeight * FixedWidthFontRenderer.FONT_HEIGHT; - this.terminal = new WidgetTerminal( this.client, () -> this.m_computer, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight, 2, 2, 2, 2 ); + this.terminal = new WidgetTerminal( this.client, () -> this.computer, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight, 2, 2, 2, 2 ); this.terminalWrapper = new WidgetWrapper( this.terminal, 2 + 8 + this.x, 2 + 8 + this.y, termPxWidth, termPxHeight ); this.children.add( this.terminalWrapper ); @@ -78,7 +78,7 @@ public class GuiTurtle extends HandledScreen protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) { // Draw term - Identifier texture = this.m_family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; + Identifier texture = this.family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; this.terminal.draw( this.terminalWrapper.getX(), this.terminalWrapper.getY() ); // Draw border/inventory @@ -88,7 +88,7 @@ public class GuiTurtle extends HandledScreen this.drawTexture( transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight ); // Draw selection slot - int slot = this.m_container.getSelectedSlot(); + int slot = this.container.getSelectedSlot(); if( slot >= 0 ) { int slotX = slot % 4; diff --git a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java index 96da1dcc7..df3e83669 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java @@ -23,23 +23,23 @@ import java.util.*; @Environment( EnvType.CLIENT ) public class TurtleMultiModel implements BakedModel { - private final BakedModel m_baseModel; - private final BakedModel m_overlayModel; - private final AffineTransformation m_generalTransform; - private final TransformedModel m_leftUpgradeModel; - private final TransformedModel m_rightUpgradeModel; - private List m_generalQuads = null; - private Map> m_faceQuads = new EnumMap<>( Direction.class ); + private final BakedModel baseModel; + private final BakedModel overlayModel; + private final AffineTransformation generalTransform; + private final TransformedModel leftUpgradeModel; + private final TransformedModel rightUpgradeModel; + private List generalQuads = null; + private Map> faceQuads = new EnumMap<>( Direction.class ); public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, AffineTransformation generalTransform, TransformedModel leftUpgradeModel, TransformedModel rightUpgradeModel ) { // Get the models - this.m_baseModel = baseModel; - this.m_overlayModel = overlayModel; - this.m_leftUpgradeModel = leftUpgradeModel; - this.m_rightUpgradeModel = rightUpgradeModel; - this.m_generalTransform = generalTransform; + this.baseModel = baseModel; + this.overlayModel = overlayModel; + this.leftUpgradeModel = leftUpgradeModel; + this.rightUpgradeModel = rightUpgradeModel; + this.generalTransform = generalTransform; } @Nonnull @@ -48,19 +48,19 @@ public class TurtleMultiModel implements BakedModel { if( side != null ) { - if( !this.m_faceQuads.containsKey( side ) ) + if( !this.faceQuads.containsKey( side ) ) { - this.m_faceQuads.put( side, this.buildQuads( state, side, rand ) ); + this.faceQuads.put( side, this.buildQuads( state, side, rand ) ); } - return this.m_faceQuads.get( side ); + return this.faceQuads.get( side ); } else { - if( this.m_generalQuads == null ) + if( this.generalQuads == null ) { - this.m_generalQuads = this.buildQuads( state, side, rand ); + this.generalQuads = this.buildQuads( state, side, rand ); } - return this.m_generalQuads; + return this.generalQuads; } } @@ -69,22 +69,22 @@ public class TurtleMultiModel implements BakedModel ArrayList quads = new ArrayList<>(); - ModelTransformer.transformQuadsTo( quads, this.m_baseModel.getQuads( state, side, rand ), this.m_generalTransform.getMatrix() ); - if( this.m_overlayModel != null ) + ModelTransformer.transformQuadsTo( quads, this.baseModel.getQuads( state, side, rand ), this.generalTransform.getMatrix() ); + if( this.overlayModel != null ) { - ModelTransformer.transformQuadsTo( quads, this.m_overlayModel.getQuads( state, side, rand ), this.m_generalTransform.getMatrix() ); + ModelTransformer.transformQuadsTo( quads, this.overlayModel.getQuads( state, side, rand ), this.generalTransform.getMatrix() ); } - if( this.m_leftUpgradeModel != null ) + if( this.leftUpgradeModel != null ) { - AffineTransformation upgradeTransform = this.m_generalTransform.multiply( this.m_leftUpgradeModel.getMatrix() ); - ModelTransformer.transformQuadsTo( quads, this.m_leftUpgradeModel.getModel() + AffineTransformation upgradeTransform = this.generalTransform.multiply( this.leftUpgradeModel.getMatrix() ); + ModelTransformer.transformQuadsTo( quads, this.leftUpgradeModel.getModel() .getQuads( state, side, rand ), upgradeTransform.getMatrix() ); } - if( this.m_rightUpgradeModel != null ) + if( this.rightUpgradeModel != null ) { - AffineTransformation upgradeTransform = this.m_generalTransform.multiply( this.m_rightUpgradeModel.getMatrix() ); - ModelTransformer.transformQuadsTo( quads, this.m_rightUpgradeModel.getModel() + AffineTransformation upgradeTransform = this.generalTransform.multiply( this.rightUpgradeModel.getMatrix() ); + ModelTransformer.transformQuadsTo( quads, this.rightUpgradeModel.getModel() .getQuads( state, side, rand ), upgradeTransform.getMatrix() ); } @@ -95,25 +95,25 @@ public class TurtleMultiModel implements BakedModel @Override public boolean useAmbientOcclusion() { - return this.m_baseModel.useAmbientOcclusion(); + return this.baseModel.useAmbientOcclusion(); } @Override public boolean hasDepth() { - return this.m_baseModel.hasDepth(); + return this.baseModel.hasDepth(); } @Override public boolean isSideLit() { - return this.m_baseModel.isSideLit(); + return this.baseModel.isSideLit(); } @Override public boolean isBuiltin() { - return this.m_baseModel.isBuiltin(); + return this.baseModel.isBuiltin(); } @Nonnull @@ -121,7 +121,7 @@ public class TurtleMultiModel implements BakedModel @Deprecated public Sprite getSprite() { - return this.m_baseModel.getSprite(); + return this.baseModel.getSprite(); } @Nonnull @@ -129,7 +129,7 @@ public class TurtleMultiModel implements BakedModel @Deprecated public net.minecraft.client.render.model.json.ModelTransformation getTransformation() { - return this.m_baseModel.getTransformation(); + return this.baseModel.getTransformation(); } @Nonnull diff --git a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java index dcad3b2db..d0056ec90 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java @@ -57,8 +57,8 @@ public class TurtleSmartItemModel implements BakedModel private final BakedModel familyModel; private final BakedModel colourModel; - private final HashMap m_cachedModels = new HashMap<>(); - private final ModelOverrideList m_overrides; + private final HashMap cachedModels = new HashMap<>(); + private final ModelOverrideList overrides; public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel ) { @@ -66,7 +66,7 @@ public class TurtleSmartItemModel implements BakedModel this.colourModel = colourModel; // this actually works I think, trust me - this.m_overrides = new ModelOverrideList( null, null, null, Collections.emptyList() ) + this.overrides = new ModelOverrideList( null, null, null, Collections.emptyList() ) { @Nonnull @Override @@ -85,10 +85,10 @@ public class TurtleSmartItemModel implements BakedModel boolean flip = false; TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip ); - BakedModel model = TurtleSmartItemModel.this.m_cachedModels.get( combo ); + BakedModel model = TurtleSmartItemModel.this.cachedModels.get( combo ); if( model == null ) { - TurtleSmartItemModel.this.m_cachedModels.put( combo, model = TurtleSmartItemModel.this.buildModel( combo ) ); + TurtleSmartItemModel.this.cachedModels.put( combo, model = TurtleSmartItemModel.this.buildModel( combo ) ); } return model; } @@ -101,13 +101,13 @@ public class TurtleSmartItemModel implements BakedModel BakedModelManager modelManager = mc.getItemRenderer() .getModels() .getModelManager(); - ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas ); + ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas ); - BakedModel baseModel = combo.m_colour ? this.colourModel : this.familyModel; + BakedModel baseModel = combo.colour ? this.colourModel : this.familyModel; BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null; - AffineTransformation transform = combo.m_flip ? flip : identity; - TransformedModel leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.LEFT ) : null; - TransformedModel rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null; + AffineTransformation transform = combo.flip ? flip : identity; + TransformedModel leftModel = combo.leftUpgrade != null ? combo.leftUpgrade.getModel( null, TurtleSide.LEFT ) : null; + TransformedModel rightModel = combo.rightUpgrade != null ? combo.rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null; return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel, rightModel ); } @@ -163,27 +163,27 @@ public class TurtleSmartItemModel implements BakedModel @Override public ModelOverrideList getOverrides() { - return this.m_overrides; + return this.overrides; } private static class TurtleModelCombination { - final boolean m_colour; - final ITurtleUpgrade m_leftUpgrade; - final ITurtleUpgrade m_rightUpgrade; - final Identifier m_overlay; - final boolean m_christmas; - final boolean m_flip; + final boolean colour; + final ITurtleUpgrade leftUpgrade; + final ITurtleUpgrade rightUpgrade; + final Identifier overlay; + final boolean christmas; + final boolean flip; TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas, boolean flip ) { - this.m_colour = colour; - this.m_leftUpgrade = leftUpgrade; - this.m_rightUpgrade = rightUpgrade; - this.m_overlay = overlay; - this.m_christmas = christmas; - this.m_flip = flip; + this.colour = colour; + this.leftUpgrade = leftUpgrade; + this.rightUpgrade = rightUpgrade; + this.overlay = overlay; + this.christmas = christmas; + this.flip = flip; } @Override @@ -191,12 +191,12 @@ public class TurtleSmartItemModel implements BakedModel { final int prime = 31; int result = 0; - result = prime * result + (this.m_colour ? 1 : 0); - result = prime * result + (this.m_leftUpgrade != null ? this.m_leftUpgrade.hashCode() : 0); - result = prime * result + (this.m_rightUpgrade != null ? this.m_rightUpgrade.hashCode() : 0); - result = prime * result + (this.m_overlay != null ? this.m_overlay.hashCode() : 0); - result = prime * result + (this.m_christmas ? 1 : 0); - result = prime * result + (this.m_flip ? 1 : 0); + result = prime * result + (this.colour ? 1 : 0); + result = prime * result + (this.leftUpgrade != null ? this.leftUpgrade.hashCode() : 0); + result = prime * result + (this.rightUpgrade != null ? this.rightUpgrade.hashCode() : 0); + result = prime * result + (this.overlay != null ? this.overlay.hashCode() : 0); + result = prime * result + (this.christmas ? 1 : 0); + result = prime * result + (this.flip ? 1 : 0); return result; } @@ -213,8 +213,8 @@ public class TurtleSmartItemModel implements BakedModel } TurtleModelCombination otherCombo = (TurtleModelCombination) other; - return otherCombo.m_colour == this.m_colour && otherCombo.m_leftUpgrade == this.m_leftUpgrade && otherCombo.m_rightUpgrade == this.m_rightUpgrade && Objects.equal( - otherCombo.m_overlay, this.m_overlay ) && otherCombo.m_christmas == this.m_christmas && otherCombo.m_flip == this.m_flip; + return otherCombo.colour == this.colour && otherCombo.leftUpgrade == this.leftUpgrade && otherCombo.rightUpgrade == this.rightUpgrade && Objects.equal( + otherCombo.overlay, this.overlay ) && otherCombo.christmas == this.christmas && otherCombo.flip == this.flip; } } diff --git a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java index e3fd875fb..30a8d0679 100644 --- a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java @@ -12,21 +12,21 @@ import net.minecraft.nbt.CompoundTag; public class ClientTerminal implements ITerminal { - private boolean m_colour; - private Terminal m_terminal; - private boolean m_terminalChanged; + private boolean colour; + private Terminal terminal; + private boolean terminalChanged; public ClientTerminal( boolean colour ) { - this.m_colour = colour; - this.m_terminal = null; - this.m_terminalChanged = false; + this.colour = colour; + this.terminal = null; + this.terminalChanged = false; } public boolean pollTerminalChanged() { - boolean changed = this.m_terminalChanged; - this.m_terminalChanged = false; + boolean changed = this.terminalChanged; + this.terminalChanged = false; return changed; } @@ -35,22 +35,22 @@ public class ClientTerminal implements ITerminal @Override public Terminal getTerminal() { - return this.m_terminal; + return this.terminal; } @Override public boolean isColour() { - return this.m_colour; + return this.colour; } public void read( TerminalState state ) { - this.m_colour = state.colour; + this.colour = state.colour; if( state.hasTerminal() ) { this.resizeTerminal( state.width, state.height ); - state.apply( this.m_terminal ); + state.apply( this.terminal ); } else { @@ -60,34 +60,34 @@ public class ClientTerminal implements ITerminal private void resizeTerminal( int width, int height ) { - if( this.m_terminal == null ) + if( this.terminal == null ) { - this.m_terminal = new Terminal( width, height, () -> this.m_terminalChanged = true ); - this.m_terminalChanged = true; + this.terminal = new Terminal( width, height, () -> this.terminalChanged = true ); + this.terminalChanged = true; } else { - this.m_terminal.resize( width, height ); + this.terminal.resize( width, height ); } } private void deleteTerminal() { - if( this.m_terminal != null ) + if( this.terminal != null ) { - this.m_terminal = null; - this.m_terminalChanged = true; + this.terminal = null; + this.terminalChanged = true; } } public void readDescription( CompoundTag nbt ) { - this.m_colour = nbt.getBoolean( "colour" ); + this.colour = nbt.getBoolean( "colour" ); if( nbt.contains( "terminal" ) ) { CompoundTag terminal = nbt.getCompound( "terminal" ); this.resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) ); - this.m_terminal.readFromNBT( terminal ); + this.terminal.readFromNBT( terminal ); } else { diff --git a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java index 294335aa1..70c76b463 100644 --- a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java @@ -14,86 +14,86 @@ import java.util.concurrent.atomic.AtomicBoolean; public class ServerTerminal implements ITerminal { - private final boolean m_colour; - private final AtomicBoolean m_terminalChanged = new AtomicBoolean( false ); - private Terminal m_terminal; - private boolean m_terminalChangedLastFrame = false; + private final boolean colour; + private final AtomicBoolean terminalChanged = new AtomicBoolean( false ); + private Terminal terminal; + private boolean terminalChangedLastFrame = false; public ServerTerminal( boolean colour ) { - this.m_colour = colour; - this.m_terminal = null; + this.colour = colour; + this.terminal = null; } public ServerTerminal( boolean colour, int terminalWidth, int terminalHeight ) { - this.m_colour = colour; - this.m_terminal = new Terminal( terminalWidth, terminalHeight, this::markTerminalChanged ); + this.colour = colour; + this.terminal = new Terminal( terminalWidth, terminalHeight, this::markTerminalChanged ); } protected void markTerminalChanged() { - this.m_terminalChanged.set( true ); + this.terminalChanged.set( true ); } protected void resize( int width, int height ) { - if( this.m_terminal == null ) + if( this.terminal == null ) { - this.m_terminal = new Terminal( width, height, this::markTerminalChanged ); + this.terminal = new Terminal( width, height, this::markTerminalChanged ); this.markTerminalChanged(); } else { - this.m_terminal.resize( width, height ); + this.terminal.resize( width, height ); } } public void delete() { - if( this.m_terminal != null ) + if( this.terminal != null ) { - this.m_terminal = null; + this.terminal = null; this.markTerminalChanged(); } } public void update() { - this.m_terminalChangedLastFrame = this.m_terminalChanged.getAndSet( false ); + this.terminalChangedLastFrame = this.terminalChanged.getAndSet( false ); } public boolean hasTerminalChanged() { - return this.m_terminalChangedLastFrame; + return this.terminalChangedLastFrame; } @Override public Terminal getTerminal() { - return this.m_terminal; + return this.terminal; } @Override public boolean isColour() { - return this.m_colour; + return this.colour; } public TerminalState write() { - return new TerminalState( this.m_colour, this.m_terminal ); + return new TerminalState( this.colour, this.terminal ); } public void writeDescription( CompoundTag nbt ) { - nbt.putBoolean( "colour", this.m_colour ); - if( this.m_terminal != null ) + nbt.putBoolean( "colour", this.colour ); + if( this.terminal != null ) { CompoundTag terminal = new CompoundTag(); - terminal.putInt( "term_width", this.m_terminal.getWidth() ); - terminal.putInt( "term_height", this.m_terminal.getHeight() ); - this.m_terminal.writeToNBT( terminal ); + terminal.putInt( "term_width", this.terminal.getWidth() ); + terminal.putInt( "term_height", this.terminal.getHeight() ); + this.terminal.writeToNBT( terminal ); nbt.put( "terminal", terminal ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java index b59a3c24a..24203b73f 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerProxy.java @@ -29,7 +29,7 @@ public class ComputerProxy ServerComputer computer = tile.getServerComputer(); if( computer == null ) { - tile.m_startOn = true; + tile.startOn = true; } else { @@ -48,7 +48,7 @@ public class ComputerProxy ServerComputer computer = tile.getServerComputer(); if( computer == null ) { - tile.m_startOn = false; + tile.startOn = false; } else { @@ -62,7 +62,7 @@ public class ComputerProxy ServerComputer computer = tile.getServerComputer(); if( computer == null ) { - tile.m_startOn = true; + tile.startOn = true; } else { diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java index a0d1e6ea7..15b38b3ed 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java @@ -56,11 +56,11 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT private static final String NBT_ON = "On"; private final ComputerFamily family; protected String label = null; - boolean m_startOn = false; - private int m_instanceID = -1; - private int m_computerID = -1; - private boolean m_on = false; - private boolean m_fresh = false; + boolean startOn = false; + private int instanceID = -1; + private int computerID = -1; + private boolean on = false; + private boolean fresh = false; public TileComputerBase( BlockEntityType type, ComputerFamily family ) { @@ -86,13 +86,13 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT protected void unload() { - if( this.m_instanceID >= 0 ) + if( this.instanceID >= 0 ) { if( !this.getWorld().isClient ) { - ComputerCraft.serverComputerRegistry.remove( this.m_instanceID ); + ComputerCraft.serverComputerRegistry.remove( this.instanceID ); } - this.m_instanceID = -1; + this.instanceID = -1; } } @@ -139,16 +139,16 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT } boolean changed = false; - if( this.m_instanceID < 0 ) + if( this.instanceID < 0 ) { - this.m_instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); + this.instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); changed = true; } - if( !ComputerCraft.serverComputerRegistry.contains( this.m_instanceID ) ) + if( !ComputerCraft.serverComputerRegistry.contains( this.instanceID ) ) { - ServerComputer computer = this.createComputer( this.m_instanceID, this.m_computerID ); - ComputerCraft.serverComputerRegistry.add( this.m_instanceID, computer ); - this.m_fresh = true; + ServerComputer computer = this.createComputer( this.instanceID, this.computerID ); + ComputerCraft.serverComputerRegistry.add( this.instanceID, computer ); + this.fresh = true; changed = true; } if( changed ) @@ -156,12 +156,12 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT this.updateBlock(); this.updateInput(); } - return ComputerCraft.serverComputerRegistry.get( this.m_instanceID ); + return ComputerCraft.serverComputerRegistry.get( this.instanceID ); } public ServerComputer getServerComputer() { - return this.getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get( this.m_instanceID ); + return this.getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get( this.instanceID ); } protected abstract ServerComputer createComputer( int instanceID, int id ); @@ -255,7 +255,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT { super.readDescription( nbt ); this.label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; - this.m_computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; + this.computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; } @Override @@ -266,9 +266,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT { nbt.putString( NBT_LABEL, this.label ); } - if( this.m_computerID >= 0 ) + if( this.computerID >= 0 ) { - nbt.putInt( NBT_ID, this.m_computerID ); + nbt.putInt( NBT_ID, this.computerID ); } } @@ -284,18 +284,18 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT } // If the computer isn't on and should be, then turn it on - if( this.m_startOn || (this.m_fresh && this.m_on) ) + if( this.startOn || (this.fresh && this.on) ) { computer.turnOn(); - this.m_startOn = false; + this.startOn = false; } computer.keepAlive(); - this.m_fresh = false; - this.m_computerID = computer.getID(); + this.fresh = false; + this.computerID = computer.getID(); this.label = computer.getLabel(); - this.m_on = computer.isOn(); + this.on = computer.isOn(); if( computer.hasOutputChanged() ) { @@ -331,9 +331,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT super.fromTag( state, nbt ); // Load ID, label and power state - this.m_computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; + this.computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; this.label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; - this.m_on = this.m_startOn = nbt.getBoolean( NBT_ON ); + this.on = this.startOn = nbt.getBoolean( NBT_ON ); } @Nonnull @@ -341,15 +341,15 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT public CompoundTag toTag( @Nonnull CompoundTag nbt ) { // Save ID, label and power state - if( this.m_computerID >= 0 ) + if( this.computerID >= 0 ) { - nbt.putInt( NBT_ID, this.m_computerID ); + nbt.putInt( NBT_ID, this.computerID ); } if( this.label != null ) { nbt.putString( NBT_LABEL, this.label ); } - nbt.putBoolean( NBT_ON, this.m_on ); + nbt.putBoolean( NBT_ON, this.on ); return super.toTag( nbt ); } @@ -407,22 +407,22 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT @Override public final int getComputerID() { - return this.m_computerID; + return this.computerID; } @Override public final void setComputerID( int id ) { - if( this.getWorld().isClient || this.m_computerID == id ) + if( this.getWorld().isClient || this.computerID == id ) { return; } - this.m_computerID = id; + this.computerID = id; ServerComputer computer = this.getServerComputer(); if( computer != null ) { - computer.setID( this.m_computerID ); + computer.setID( this.computerID ); } this.markDirty(); } @@ -460,17 +460,17 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT protected void transferStateFrom( TileComputerBase copy ) { - if( copy.m_computerID != this.m_computerID || copy.m_instanceID != this.m_instanceID ) + if( copy.computerID != this.computerID || copy.instanceID != this.instanceID ) { this.unload(); - this.m_instanceID = copy.m_instanceID; - this.m_computerID = copy.m_computerID; + this.instanceID = copy.instanceID; + this.computerID = copy.computerID; this.label = copy.label; - this.m_on = copy.m_on; - this.m_startOn = copy.m_startOn; + this.on = copy.on; + this.startOn = copy.startOn; this.updateBlock(); } - copy.m_instanceID = -1; + copy.instanceID = -1; } @Nonnull diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java index dece0c369..8ce7d7759 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java @@ -13,22 +13,22 @@ import net.minecraft.nbt.CompoundTag; public class ClientComputer extends ClientTerminal implements IComputer { - private final int m_instanceID; + private final int instanceID; - private boolean m_on = false; - private boolean m_blinking = false; - private CompoundTag m_userData = null; + private boolean on = false; + private boolean blinking = false; + private CompoundTag userData = null; public ClientComputer( int instanceID ) { super( false ); - this.m_instanceID = instanceID; + this.instanceID = instanceID; } public CompoundTag getUserData() { - return this.m_userData; + return this.userData; } public void requestState() @@ -42,53 +42,53 @@ public class ClientComputer extends ClientTerminal implements IComputer @Override public int getInstanceID() { - return this.m_instanceID; + return this.instanceID; } @Override public void turnOn() { // Send turnOn to server - NetworkHandler.sendToServer( new ComputerActionServerMessage( this.m_instanceID, ComputerActionServerMessage.Action.TURN_ON ) ); + NetworkHandler.sendToServer( new ComputerActionServerMessage( this.instanceID, ComputerActionServerMessage.Action.TURN_ON ) ); } @Override public void shutdown() { // Send shutdown to server - NetworkHandler.sendToServer( new ComputerActionServerMessage( this.m_instanceID, ComputerActionServerMessage.Action.SHUTDOWN ) ); + NetworkHandler.sendToServer( new ComputerActionServerMessage( this.instanceID, ComputerActionServerMessage.Action.SHUTDOWN ) ); } @Override public void reboot() { // Send reboot to server - NetworkHandler.sendToServer( new ComputerActionServerMessage( this.m_instanceID, ComputerActionServerMessage.Action.REBOOT ) ); + NetworkHandler.sendToServer( new ComputerActionServerMessage( this.instanceID, ComputerActionServerMessage.Action.REBOOT ) ); } @Override public void queueEvent( String event, Object[] arguments ) { // Send event to server - NetworkHandler.sendToServer( new QueueEventServerMessage( this.m_instanceID, event, arguments ) ); + NetworkHandler.sendToServer( new QueueEventServerMessage( this.instanceID, event, arguments ) ); } @Override public boolean isOn() { - return this.m_on; + return this.on; } @Override public boolean isCursorDisplayed() { - return this.m_on && this.m_blinking; + return this.on && this.blinking; } @Override public void keyDown( int key, boolean repeat ) { - NetworkHandler.sendToServer( new KeyEventServerMessage( this.m_instanceID, + NetworkHandler.sendToServer( new KeyEventServerMessage( this.instanceID, repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, key ) ); } @@ -96,37 +96,37 @@ public class ClientComputer extends ClientTerminal implements IComputer @Override public void keyUp( int key ) { - NetworkHandler.sendToServer( new KeyEventServerMessage( this.m_instanceID, KeyEventServerMessage.TYPE_UP, key ) ); + NetworkHandler.sendToServer( new KeyEventServerMessage( this.instanceID, KeyEventServerMessage.TYPE_UP, key ) ); } @Override public void mouseClick( int button, int x, int y ) { - NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_CLICK, button, x, y ) ); + NetworkHandler.sendToServer( new MouseEventServerMessage( this.instanceID, MouseEventServerMessage.TYPE_CLICK, button, x, y ) ); } @Override public void mouseUp( int button, int x, int y ) { - NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_UP, button, x, y ) ); + NetworkHandler.sendToServer( new MouseEventServerMessage( this.instanceID, MouseEventServerMessage.TYPE_UP, button, x, y ) ); } @Override public void mouseDrag( int button, int x, int y ) { - NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_DRAG, button, x, y ) ); + NetworkHandler.sendToServer( new MouseEventServerMessage( this.instanceID, MouseEventServerMessage.TYPE_DRAG, button, x, y ) ); } @Override public void mouseScroll( int direction, int x, int y ) { - NetworkHandler.sendToServer( new MouseEventServerMessage( this.m_instanceID, MouseEventServerMessage.TYPE_SCROLL, direction, x, y ) ); + NetworkHandler.sendToServer( new MouseEventServerMessage( this.instanceID, MouseEventServerMessage.TYPE_SCROLL, direction, x, y ) ); } public void setState( ComputerState state, CompoundTag userData ) { - this.m_on = state != ComputerState.OFF; - this.m_blinking = state == ComputerState.BLINKING; - this.m_userData = userData; + this.on = state != ComputerState.OFF; + this.blinking = state == ComputerState.BLINKING; + this.userData = userData; } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java b/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java index bc80c4cae..aa1b0a438 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java @@ -13,45 +13,45 @@ import java.util.Random; public class ComputerRegistry { - private Map m_computers; - private int m_nextUnusedInstanceID; - private int m_sessionID; + private final Map computers; + private int nextUnusedInstanceID; + private int sessionID; protected ComputerRegistry() { - this.m_computers = new HashMap<>(); + this.computers = new HashMap<>(); this.reset(); } public void reset() { - this.m_computers.clear(); - this.m_nextUnusedInstanceID = 0; - this.m_sessionID = new Random().nextInt(); + this.computers.clear(); + this.nextUnusedInstanceID = 0; + this.sessionID = new Random().nextInt(); } public int getSessionID() { - return this.m_sessionID; + return this.sessionID; } public int getUnusedInstanceID() { - return this.m_nextUnusedInstanceID++; + return this.nextUnusedInstanceID++; } public Collection getComputers() { - return this.m_computers.values(); + return this.computers.values(); } public T get( int instanceID ) { if( instanceID >= 0 ) { - if( this.m_computers.containsKey( instanceID ) ) + if( this.computers.containsKey( instanceID ) ) { - return this.m_computers.get( instanceID ); + return this.computers.get( instanceID ); } } return null; @@ -59,21 +59,21 @@ public class ComputerRegistry public boolean contains( int instanceID ) { - return this.m_computers.containsKey( instanceID ); + return this.computers.containsKey( instanceID ); } public void add( int instanceID, T computer ) { - if( this.m_computers.containsKey( instanceID ) ) + if( this.computers.containsKey( instanceID ) ) { this.remove( instanceID ); } - this.m_computers.put( instanceID, computer ); - this.m_nextUnusedInstanceID = Math.max( this.m_nextUnusedInstanceID, instanceID + 1 ); + this.computers.put( instanceID, computer ); + this.nextUnusedInstanceID = Math.max( this.nextUnusedInstanceID, instanceID + 1 ); } public void remove( int instanceID ) { - this.m_computers.remove( instanceID ); + this.computers.remove( instanceID ); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java index f5c23375d..1cec31629 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java @@ -37,109 +37,109 @@ import java.io.InputStream; public class ServerComputer extends ServerTerminal implements IComputer, IComputerEnvironment { - private final int m_instanceID; - private final ComputerFamily m_family; - private final Computer m_computer; - private World m_world; - private BlockPos m_position; - private CompoundTag m_userData; - private boolean m_changed; + private final int instanceID; + private final ComputerFamily family; + private final Computer computer; + private World world; + private BlockPos position; + private CompoundTag userData; + private boolean changed; - private boolean m_changedLastFrame; - private int m_ticksSincePing; + private boolean changedLastFrame; + private int ticksSincePing; public ServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight ) { super( family != ComputerFamily.NORMAL, terminalWidth, terminalHeight ); - this.m_instanceID = instanceID; + this.instanceID = instanceID; - this.m_world = world; - this.m_position = null; + this.world = world; + this.position = null; - this.m_family = family; - this.m_computer = new Computer( this, this.getTerminal(), computerID ); - this.m_computer.setLabel( label ); - this.m_userData = null; - this.m_changed = false; + this.family = family; + this.computer = new Computer( this, this.getTerminal(), computerID ); + this.computer.setLabel( label ); + this.userData = null; + this.changed = false; - this.m_changedLastFrame = false; - this.m_ticksSincePing = 0; + this.changedLastFrame = false; + this.ticksSincePing = 0; } public ComputerFamily getFamily() { - return this.m_family; + return this.family; } public World getWorld() { - return this.m_world; + return this.world; } public void setWorld( World world ) { - this.m_world = world; + this.world = world; } public BlockPos getPosition() { - return this.m_position; + return this.position; } public void setPosition( BlockPos pos ) { - this.m_position = new BlockPos( pos ); + this.position = new BlockPos( pos ); } public IAPIEnvironment getAPIEnvironment() { - return this.m_computer.getAPIEnvironment(); + return this.computer.getAPIEnvironment(); } public Computer getComputer() { - return this.m_computer; + return this.computer; } @Override public void update() { super.update(); - this.m_computer.tick(); + this.computer.tick(); - this.m_changedLastFrame = this.m_computer.pollAndResetChanged() || this.m_changed; - this.m_changed = false; + this.changedLastFrame = this.computer.pollAndResetChanged() || this.changed; + this.changed = false; - this.m_ticksSincePing++; + this.ticksSincePing++; } public void keepAlive() { - this.m_ticksSincePing = 0; + this.ticksSincePing = 0; } public boolean hasTimedOut() { - return this.m_ticksSincePing > 100; + return this.ticksSincePing > 100; } public void unload() { - this.m_computer.unload(); + this.computer.unload(); } public CompoundTag getUserData() { - if( this.m_userData == null ) + if( this.userData == null ) { - this.m_userData = new CompoundTag(); + this.userData = new CompoundTag(); } - return this.m_userData; + return this.userData; } public void updateUserData() { - this.m_changed = true; + this.changed = true; } public void broadcastState( boolean force ) @@ -180,7 +180,7 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput public boolean hasOutputChanged() { - return this.m_changedLastFrame; + return this.changedLastFrame; } private NetworkMessage createComputerPacket() @@ -219,14 +219,14 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput @Override public int getInstanceID() { - return this.m_instanceID; + return this.instanceID; } @Override public void turnOn() { // Turn on - this.m_computer.turnOn(); + this.computer.turnOn(); } // IComputer @@ -235,33 +235,33 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput public void shutdown() { // Shutdown - this.m_computer.shutdown(); + this.computer.shutdown(); } @Override public void reboot() { // Reboot - this.m_computer.reboot(); + this.computer.reboot(); } @Override public void queueEvent( String event, Object[] arguments ) { // Queue event - this.m_computer.queueEvent( event, arguments ); + this.computer.queueEvent( event, arguments ); } @Override public boolean isOn() { - return this.m_computer.isOn(); + return this.computer.isOn(); } @Override public boolean isCursorDisplayed() { - return this.m_computer.isOn() && this.m_computer.isBlinking(); + return this.computer.isOn() && this.computer.isBlinking(); } public void sendComputerState( PlayerEntity player ) @@ -288,77 +288,77 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput public int getID() { - return this.m_computer.getID(); + return this.computer.getID(); } public void setID( int id ) { - this.m_computer.setID( id ); + this.computer.setID( id ); } public String getLabel() { - return this.m_computer.getLabel(); + return this.computer.getLabel(); } public void setLabel( String label ) { - this.m_computer.setLabel( label ); + this.computer.setLabel( label ); } public int getRedstoneOutput( ComputerSide side ) { - return this.m_computer.getEnvironment() + return this.computer.getEnvironment() .getExternalRedstoneOutput( side ); } public void setRedstoneInput( ComputerSide side, int level ) { - this.m_computer.getEnvironment() + this.computer.getEnvironment() .setRedstoneInput( side, level ); } public int getBundledRedstoneOutput( ComputerSide side ) { - return this.m_computer.getEnvironment() + return this.computer.getEnvironment() .getExternalBundledRedstoneOutput( side ); } public void setBundledRedstoneInput( ComputerSide side, int combination ) { - this.m_computer.getEnvironment() + this.computer.getEnvironment() .setBundledRedstoneInput( side, combination ); } public void addAPI( ILuaAPI api ) { - this.m_computer.addApi( api ); + this.computer.addApi( api ); } // IComputerEnvironment implementation public void setPeripheral( ComputerSide side, IPeripheral peripheral ) { - this.m_computer.getEnvironment() + this.computer.getEnvironment() .setPeripheral( side, peripheral ); } public IPeripheral getPeripheral( ComputerSide side ) { - return this.m_computer.getEnvironment() + return this.computer.getEnvironment() .getPeripheral( side ); } @Override public int getDay() { - return (int) ((this.m_world.getTimeOfDay() + 6000) / 24000) + 1; + return (int) ((this.world.getTimeOfDay() + 6000) / 24000) + 1; } @Override public double getTimeOfDay() { - return (this.m_world.getTimeOfDay() + 6000) % 24000 / 1000.0; + return (this.world.getTimeOfDay() + 6000) % 24000 / 1000.0; } @Override @@ -384,13 +384,13 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput @Override public int assignNewID() { - return ComputerCraftAPI.createUniqueNumberedSaveDir( this.m_world, "computer" ); + return ComputerCraftAPI.createUniqueNumberedSaveDir( this.world, "computer" ); } @Override public IWritableMount createSaveDirMount( String subPath, long capacity ) { - return ComputerCraftAPI.createSaveDirMount( this.m_world, subPath, capacity ); + return ComputerCraftAPI.createSaveDirMount( this.world, subPath, capacity ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java index 23a2fc3bd..25066fbec 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java @@ -47,15 +47,15 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory { private static final String NBT_NAME = "CustomName"; private static final String NBT_ITEM = "Item"; - private final Map m_computers = new HashMap<>(); + private final Map computers = new HashMap<>(); Text customName; @Nonnull - private ItemStack m_diskStack = ItemStack.EMPTY; - private IMount m_diskMount = null; - private boolean m_recordQueued = false; - private boolean m_recordPlaying = false; - private boolean m_restartRecord = false; - private boolean m_ejectQueued; + private ItemStack diskStack = ItemStack.EMPTY; + private IMount diskMount = null; + private boolean recordQueued = false; + private boolean recordPlaying = false; + private boolean restartRecord = false; + private boolean ejectQueued; public TileDiskDrive( BlockEntityType type ) { @@ -66,7 +66,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory public void destroy() { this.ejectContents( true ); - if( this.m_recordPlaying ) + if( this.recordPlaying ) { this.stopRecord(); } @@ -115,8 +115,8 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory if( nbt.contains( NBT_ITEM ) ) { CompoundTag item = nbt.getCompound( NBT_ITEM ); - this.m_diskStack = ItemStack.fromTag( item ); - this.m_diskMount = null; + this.diskStack = ItemStack.fromTag( item ); + this.diskMount = null; } } @@ -129,10 +129,10 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory nbt.putString( NBT_NAME, Text.Serializer.toJson( this.customName ) ); } - if( !this.m_diskStack.isEmpty() ) + if( !this.diskStack.isEmpty() ) { CompoundTag item = new CompoundTag(); - this.m_diskStack.toTag( item ); + this.diskStack.toTag( item ); nbt.put( NBT_ITEM, item ); } return super.toTag( nbt ); @@ -152,36 +152,36 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory public void tick() { // Ejection - if( this.m_ejectQueued ) + if( this.ejectQueued ) { this.ejectContents( false ); - this.m_ejectQueued = false; + this.ejectQueued = false; } // Music synchronized( this ) { - if( !this.world.isClient && this.m_recordPlaying != this.m_recordQueued || this.m_restartRecord ) + if( !this.world.isClient && this.recordPlaying != this.recordQueued || this.restartRecord ) { - this.m_restartRecord = false; - if( this.m_recordQueued ) + this.restartRecord = false; + if( this.recordQueued ) { IMedia contents = this.getDiskMedia(); - SoundEvent record = contents != null ? contents.getAudio( this.m_diskStack ) : null; + SoundEvent record = contents != null ? contents.getAudio( this.diskStack ) : null; if( record != null ) { - this.m_recordPlaying = true; + this.recordPlaying = true; this.playRecord(); } else { - this.m_recordQueued = false; + this.recordQueued = false; } } else { this.stopRecord(); - this.m_recordPlaying = false; + this.recordPlaying = false; } } } @@ -198,34 +198,34 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory @Override public boolean isEmpty() { - return this.m_diskStack.isEmpty(); + return this.diskStack.isEmpty(); } @Nonnull @Override public ItemStack getStack( int slot ) { - return this.m_diskStack; + return this.diskStack; } @Nonnull @Override public ItemStack removeStack( int slot, int count ) { - if( this.m_diskStack.isEmpty() ) + if( this.diskStack.isEmpty() ) { return ItemStack.EMPTY; } - if( this.m_diskStack.getCount() <= count ) + if( this.diskStack.getCount() <= count ) { - ItemStack disk = this.m_diskStack; + ItemStack disk = this.diskStack; this.setStack( slot, ItemStack.EMPTY ); return disk; } - ItemStack part = this.m_diskStack.split( count ); - this.setStack( slot, this.m_diskStack.isEmpty() ? ItemStack.EMPTY : this.m_diskStack ); + ItemStack part = this.diskStack.split( count ); + this.setStack( slot, this.diskStack.isEmpty() ? ItemStack.EMPTY : this.diskStack ); return part; } @@ -233,9 +233,9 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory @Override public ItemStack removeStack( int slot ) { - ItemStack result = this.m_diskStack; - this.m_diskStack = ItemStack.EMPTY; - this.m_diskMount = null; + ItemStack result = this.diskStack; + this.diskStack = ItemStack.EMPTY; + this.diskMount = null; return result; } @@ -245,25 +245,25 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory { if( this.getWorld().isClient ) { - this.m_diskStack = stack; - this.m_diskMount = null; + this.diskStack = stack; + this.diskMount = null; this.markDirty(); return; } synchronized( this ) { - if( InventoryUtil.areItemsStackable( stack, this.m_diskStack ) ) + if( InventoryUtil.areItemsStackable( stack, this.diskStack ) ) { - this.m_diskStack = stack; + this.diskStack = stack; return; } // Unmount old disk - if( !this.m_diskStack.isEmpty() ) + if( !this.diskStack.isEmpty() ) { // TODO: Is this iteration thread safe? - Set computers = this.m_computers.keySet(); + Set computers = this.computers.keySet(); for( IComputerAccess computer : computers ) { this.unmountDisk( computer ); @@ -271,22 +271,22 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory } // Stop music - if( this.m_recordPlaying ) + if( this.recordPlaying ) { this.stopRecord(); - this.m_recordPlaying = false; - this.m_recordQueued = false; + this.recordPlaying = false; + this.recordQueued = false; } // Swap disk over - this.m_diskStack = stack; - this.m_diskMount = null; + this.diskStack = stack; + this.diskMount = null; this.markDirty(); // Mount new disk - if( !this.m_diskStack.isEmpty() ) + if( !this.diskStack.isEmpty() ) { - Set computers = this.m_computers.keySet(); + Set computers = this.computers.keySet(); for( IComputerAccess computer : computers ) { this.mountDisk( computer ); @@ -318,7 +318,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory { synchronized( this ) { - MountInfo info = this.m_computers.get( computer ); + MountInfo info = this.computers.get( computer ); return info != null ? info.mountPath : null; } } @@ -327,32 +327,32 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory { synchronized( this ) { - this.m_computers.put( computer, new MountInfo() ); + this.computers.put( computer, new MountInfo() ); this.mountDisk( computer ); } } private synchronized void mountDisk( IComputerAccess computer ) { - if( !this.m_diskStack.isEmpty() ) + if( !this.diskStack.isEmpty() ) { - MountInfo info = this.m_computers.get( computer ); + MountInfo info = this.computers.get( computer ); IMedia contents = this.getDiskMedia(); if( contents != null ) { - if( this.m_diskMount == null ) + if( this.diskMount == null ) { - this.m_diskMount = contents.createDataMount( this.m_diskStack, this.getWorld() ); + this.diskMount = contents.createDataMount( this.diskStack, this.getWorld() ); } - if( this.m_diskMount != null ) + if( this.diskMount != null ) { - if( this.m_diskMount instanceof IWritableMount ) + if( this.diskMount instanceof IWritableMount ) { // Try mounting at the lowest numbered "disk" name we can int n = 1; while( info.mountPath == null ) { - info.mountPath = computer.mountWritable( n == 1 ? "disk" : "disk" + n, (IWritableMount) this.m_diskMount ); + info.mountPath = computer.mountWritable( n == 1 ? "disk" : "disk" + n, (IWritableMount) this.diskMount ); n++; } } @@ -362,7 +362,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory int n = 1; while( info.mountPath == null ) { - info.mountPath = computer.mount( n == 1 ? "disk" : "disk" + n, this.m_diskMount ); + info.mountPath = computer.mount( n == 1 ? "disk" : "disk" + n, this.diskMount ); n++; } } @@ -397,15 +397,15 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory synchronized( this ) { this.unmountDisk( computer ); - this.m_computers.remove( computer ); + this.computers.remove( computer ); } } private synchronized void unmountDisk( IComputerAccess computer ) { - if( !this.m_diskStack.isEmpty() ) + if( !this.diskStack.isEmpty() ) { - MountInfo info = this.m_computers.get( computer ); + MountInfo info = this.computers.get( computer ); assert info != null; if( info.mountPath != null ) { @@ -421,10 +421,10 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory synchronized( this ) { IMedia media = this.getDiskMedia(); - if( media != null && media.getAudioTitle( this.m_diskStack ) != null ) + if( media != null && media.getAudioTitle( this.diskStack ) != null ) { - this.m_recordQueued = true; - this.m_restartRecord = this.m_recordPlaying; + this.recordQueued = true; + this.restartRecord = this.recordPlaying; } } } @@ -433,8 +433,8 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory { synchronized( this ) { - this.m_recordQueued = false; - this.m_restartRecord = false; + this.recordQueued = false; + this.restartRecord = false; } } @@ -444,7 +444,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory { synchronized( this ) { - this.m_ejectQueued = true; + this.ejectQueued = true; } } @@ -455,7 +455,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory return; } - if( !this.m_diskStack.isEmpty() ) + if( !this.diskStack.isEmpty() ) { IMedia contents = this.getDiskMedia(); this.updateBlockState( contents != null ? DiskDriveState.FULL : DiskDriveState.INVALID ); @@ -479,13 +479,13 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory private synchronized void ejectContents( boolean destroyed ) { - if( this.getWorld().isClient || this.m_diskStack.isEmpty() ) + if( this.getWorld().isClient || this.diskStack.isEmpty() ) { return; } // Remove the disks from the inventory - ItemStack disks = this.m_diskStack; + ItemStack disks = this.diskStack; this.setDiskStack( ItemStack.EMPTY ); // Spawn the item in the world @@ -515,10 +515,10 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory private void playRecord() { IMedia contents = this.getDiskMedia(); - SoundEvent record = contents != null ? contents.getAudio( this.m_diskStack ) : null; + SoundEvent record = contents != null ? contents.getAudio( this.diskStack ) : null; if( record != null ) { - RecordUtil.playRecord( record, contents.getAudioTitle( this.m_diskStack ), this.getWorld(), this.getPos() ); + RecordUtil.playRecord( record, contents.getAudioTitle( this.diskStack ), this.getWorld(), this.getPos() ); } else { diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java index c73c966ae..0bc394f4e 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java @@ -28,18 +28,18 @@ import java.util.Set; */ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver { - private final Set m_computers = new HashSet<>( 1 ); - private final ModemState m_state; - private IPacketNetwork m_network; + private final Set computers = new HashSet<>( 1 ); + private final ModemState state; + private IPacketNetwork network; protected ModemPeripheral( ModemState state ) { - this.m_state = state; + this.state = state; } public ModemState getModemState() { - return this.m_state; + return this.state; } public void destroy() @@ -50,14 +50,14 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @Override public void receiveSameDimension( @Nonnull Packet packet, double distance ) { - if( packet.getSender() == this || !this.m_state.isOpen( packet.getChannel() ) ) + if( packet.getSender() == this || !this.state.isOpen( packet.getChannel() ) ) { return; } - synchronized( this.m_computers ) + synchronized( this.computers ) { - for( IComputerAccess computer : this.m_computers ) + for( IComputerAccess computer : this.computers ) { computer.queueEvent( "modem_message", computer.getAttachmentName(), @@ -72,14 +72,14 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @Override public void receiveDifferentDimension( @Nonnull Packet packet ) { - if( packet.getSender() == this || !this.m_state.isOpen( packet.getChannel() ) ) + if( packet.getSender() == this || !this.state.isOpen( packet.getChannel() ) ) { return; } - synchronized( this.m_computers ) + synchronized( this.computers ) { - for( IComputerAccess computer : this.m_computers ) + for( IComputerAccess computer : this.computers ) { computer.queueEvent( "modem_message", computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload() ); } @@ -96,9 +96,9 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @Override public synchronized void attach( @Nonnull IComputerAccess computer ) { - synchronized( this.m_computers ) + synchronized( this.computers ) { - this.m_computers.add( computer ); + this.computers.add( computer ); } this.setNetwork( this.getNetwork() ); @@ -108,24 +108,24 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa private synchronized void setNetwork( IPacketNetwork network ) { - if( this.m_network == network ) + if( this.network == network ) { return; } // Leave old network - if( this.m_network != null ) + if( this.network != null ) { - this.m_network.removeReceiver( this ); + this.network.removeReceiver( this ); } // Set new network - this.m_network = network; + this.network = network; // Join new network - if( this.m_network != null ) + if( this.network != null ) { - this.m_network.addReceiver( this ); + this.network.addReceiver( this ); } } @@ -133,10 +133,10 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa public synchronized void detach( @Nonnull IComputerAccess computer ) { boolean empty; - synchronized( this.m_computers ) + synchronized( this.computers ) { - this.m_computers.remove( computer ); - empty = this.m_computers.isEmpty(); + this.computers.remove( computer ); + empty = this.computers.isEmpty(); } if( empty ) @@ -155,7 +155,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @LuaFunction public final void open( int channel ) throws LuaException { - this.m_state.open( parseChannel( channel ) ); + this.state.open( parseChannel( channel ) ); } private static int parseChannel( int channel ) throws LuaException @@ -177,7 +177,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @LuaFunction public final boolean isOpen( int channel ) throws LuaException { - return this.m_state.isOpen( parseChannel( channel ) ); + return this.state.isOpen( parseChannel( channel ) ); } /** @@ -189,7 +189,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @LuaFunction public final void close( int channel ) throws LuaException { - this.m_state.close( parseChannel( channel ) ); + this.state.close( parseChannel( channel ) ); } /** @@ -198,7 +198,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @LuaFunction public final void closeAll() { - this.m_state.closeAll(); + this.state.closeAll(); } /** @@ -219,7 +219,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa World world = this.getWorld(); Vec3d position = this.getPosition(); - IPacketNetwork network = this.m_network; + IPacketNetwork network = this.network; if( world == null || position == null || network == null ) { @@ -247,7 +247,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @LuaFunction public final boolean isWireless() { - IPacketNetwork network = this.m_network; + IPacketNetwork network = this.network; return network != null && network.isWireless(); } @@ -255,15 +255,15 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @Override public String getSenderID() { - synchronized( this.m_computers ) + synchronized( this.computers ) { - if( this.m_computers.size() != 1 ) + if( this.computers.size() != 1 ) { return "unknown"; } else { - IComputerAccess computer = this.m_computers.iterator() + IComputerAccess computer = this.computers.iterator() .next(); return computer.getID() + "_" + computer.getAttachmentName(); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java index fe4440f24..6ac352b89 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java @@ -41,19 +41,19 @@ import java.util.Map; public class TileCable extends TileGeneric implements IPeripheralTile { private static final String NBT_PERIPHERAL_ENABLED = "PeirpheralAccess"; - private final WiredModemLocalPeripheral m_peripheral = new WiredModemLocalPeripheral(); - private final WiredModemElement m_cable = new CableElement(); - private final IWiredNode m_node = this.m_cable.getNode(); - private boolean m_peripheralAccessAllowed; - private boolean m_destroyed = false; + private final WiredModemLocalPeripheral peripheral = new WiredModemLocalPeripheral(); + private final WiredModemElement cable = new CableElement(); + private final IWiredNode node = this.cable.getNode(); + private boolean peripheralAccessAllowed; + private boolean destroyed = false; private Direction modemDirection = Direction.NORTH; - private final WiredModemPeripheral m_modem = new WiredModemPeripheral( new ModemState( () -> TickScheduler.schedule( this ) ), this.m_cable ) + private final WiredModemPeripheral modem = new WiredModemPeripheral( new ModemState( () -> TickScheduler.schedule( this ) ), this.cable ) { @Nonnull @Override protected WiredModemLocalPeripheral getLocalPeripheral() { - return TileCable.this.m_peripheral; + return TileCable.this.peripheral; } @Nonnull @@ -72,7 +72,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile } }; private boolean hasModemDirection = false; - private boolean m_connectionsFormed = false; + private boolean connectionsFormed = false; public TileCable( BlockEntityType type ) { @@ -82,10 +82,10 @@ public class TileCable extends TileGeneric implements IPeripheralTile @Override public void destroy() { - if( !this.m_destroyed ) + if( !this.destroyed ) { - this.m_destroyed = true; - this.m_modem.destroy(); + this.destroyed = true; + this.modem.destroy(); this.onRemove(); } } @@ -101,8 +101,8 @@ public class TileCable extends TileGeneric implements IPeripheralTile { if( this.world == null || !this.world.isClient ) { - this.m_node.remove(); - this.m_connectionsFormed = false; + this.node.remove(); + this.connectionsFormed = false; } } @@ -124,9 +124,9 @@ public class TileCable extends TileGeneric implements IPeripheralTile return ActionResult.SUCCESS; } - String oldName = this.m_peripheral.getConnectedName(); + String oldName = this.peripheral.getConnectedName(); this.togglePeripheralAccess(); - String newName = this.m_peripheral.getConnectedName(); + String newName = this.peripheral.getConnectedName(); if( !Objects.equal( newName, oldName ) ) { if( oldName != null ) @@ -200,11 +200,11 @@ public class TileCable extends TileGeneric implements IPeripheralTile // If we can no longer attach peripherals, then detach any // which may have existed - if( !this.canAttachPeripheral() && this.m_peripheralAccessAllowed ) + if( !this.canAttachPeripheral() && this.peripheralAccessAllowed ) { - this.m_peripheralAccessAllowed = false; - this.m_peripheral.detach(); - this.m_node.updatePeripherals( Collections.emptyMap() ); + this.peripheralAccessAllowed = false; + this.peripheral.detach(); + this.node.updatePeripherals( Collections.emptyMap() ); this.markDirty(); this.updateBlockState(); } @@ -233,17 +233,17 @@ public class TileCable extends TileGeneric implements IPeripheralTile { // TODO Figure out why this crashes. IWiredNode node = element.getNode(); - if( node != null && this.m_node != null ) + if( node != null && this.node != null ) { if( BlockCable.canConnectIn( state, facing ) ) { // If we can connect to it then do so - this.m_node.connectTo( node ); + this.node.connectTo( node ); } - else if( this.m_node.getNetwork() == node.getNetwork() ) + else if( this.node.getNetwork() == node.getNetwork() ) { // Otherwise if we're on the same network then attempt to void it. - this.m_node.disconnectFrom( node ); + this.node.disconnectFrom( node ); } } } @@ -259,8 +259,8 @@ public class TileCable extends TileGeneric implements IPeripheralTile { BlockState state = this.getCachedState(); CableModemVariant oldVariant = state.get( BlockCable.MODEM ); - CableModemVariant newVariant = CableModemVariant.from( oldVariant.getFacing(), this.m_modem.getModemState() - .isOpen(), this.m_peripheralAccessAllowed ); + CableModemVariant newVariant = CableModemVariant.from( oldVariant.getFacing(), this.modem.getModemState() + .isOpen(), this.peripheralAccessAllowed ); if( oldVariant != newVariant ) { @@ -270,7 +270,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile private void refreshPeripheral() { - if( this.world != null && !this.isRemoved() && this.m_peripheral.attach( this.world, this.getPos(), this.getDirection() ) ) + if( this.world != null && !this.isRemoved() && this.peripheral.attach( this.world, this.getPos(), this.getDirection() ) ) { this.updateConnectedPeripherals(); } @@ -278,22 +278,22 @@ public class TileCable extends TileGeneric implements IPeripheralTile private void updateConnectedPeripherals() { - Map peripherals = this.m_peripheral.toMap(); + Map peripherals = this.peripheral.toMap(); if( peripherals.isEmpty() ) { // If there are no peripherals then disable access and update the display state. - this.m_peripheralAccessAllowed = false; + this.peripheralAccessAllowed = false; this.updateBlockState(); } - this.m_node.updatePeripherals( peripherals ); + this.node.updatePeripherals( peripherals ); } @Override public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) { super.onNeighbourTileEntityChange( neighbour ); - if( !this.world.isClient && this.m_peripheralAccessAllowed ) + if( !this.world.isClient && this.peripheralAccessAllowed ) { Direction facing = this.getDirection(); if( this.getPos().offset( facing ) @@ -314,20 +314,20 @@ public class TileCable extends TileGeneric implements IPeripheralTile this.refreshDirection(); - if( this.m_modem.getModemState() + if( this.modem.getModemState() .pollChanged() ) { this.updateBlockState(); } - if( !this.m_connectionsFormed ) + if( !this.connectionsFormed ) { - this.m_connectionsFormed = true; + this.connectionsFormed = true; this.connectionsChanged(); - if( this.m_peripheralAccessAllowed ) + if( this.peripheralAccessAllowed ) { - this.m_peripheral.attach( this.world, this.pos, this.modemDirection ); + this.peripheral.attach( this.world, this.pos, this.modemDirection ); this.updateConnectedPeripherals(); } } @@ -335,23 +335,23 @@ public class TileCable extends TileGeneric implements IPeripheralTile private void togglePeripheralAccess() { - if( !this.m_peripheralAccessAllowed ) + if( !this.peripheralAccessAllowed ) { - this.m_peripheral.attach( this.world, this.getPos(), this.getDirection() ); - if( !this.m_peripheral.hasPeripheral() ) + this.peripheral.attach( this.world, this.getPos(), this.getDirection() ); + if( !this.peripheral.hasPeripheral() ) { return; } - this.m_peripheralAccessAllowed = true; - this.m_node.updatePeripherals( this.m_peripheral.toMap() ); + this.peripheralAccessAllowed = true; + this.node.updatePeripherals( this.peripheral.toMap() ); } else { - this.m_peripheral.detach(); + this.peripheral.detach(); - this.m_peripheralAccessAllowed = false; - this.m_node.updatePeripherals( Collections.emptyMap() ); + this.peripheralAccessAllowed = false; + this.node.updatePeripherals( Collections.emptyMap() ); } this.updateBlockState(); @@ -380,16 +380,16 @@ public class TileCable extends TileGeneric implements IPeripheralTile public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) { super.fromTag( state, nbt ); - this.m_peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); - this.m_peripheral.read( nbt, "" ); + this.peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); + this.peripheral.read( nbt, "" ); } @Nonnull @Override public CompoundTag toTag( CompoundTag nbt ) { - nbt.putBoolean( NBT_PERIPHERAL_ENABLED, this.m_peripheralAccessAllowed ); - this.m_peripheral.write( nbt, "" ); + nbt.putBoolean( NBT_PERIPHERAL_ENABLED, this.peripheralAccessAllowed ); + this.peripheral.write( nbt, "" ); return super.toTag( nbt ); } @@ -422,14 +422,14 @@ public class TileCable extends TileGeneric implements IPeripheralTile public IWiredElement getElement( Direction facing ) { - return BlockCable.canConnectIn( this.getCachedState(), facing ) ? this.m_cable : null; + return BlockCable.canConnectIn( this.getCachedState(), facing ) ? this.cable : null; } @Nonnull @Override public IPeripheral getPeripheral( Direction side ) { - return !this.m_destroyed && this.hasModem() && side == this.getDirection() ? this.m_modem : null; + return !this.destroyed && this.hasModem() && side == this.getDirection() ? this.modem : null; } private class CableElement extends WiredModemElement @@ -452,13 +452,13 @@ public class TileCable extends TileGeneric implements IPeripheralTile @Override protected void attachPeripheral( String name, IPeripheral peripheral ) { - TileCable.this.m_modem.attachPeripheral( name, peripheral ); + TileCable.this.modem.attachPeripheral( name, peripheral ); } @Override protected void detachPeripheral( String name ) { - TileCable.this.m_modem.detachPeripheral( name ); + TileCable.this.modem.detachPeripheral( name ); } } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java index 886585ebc..634f529fd 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java @@ -41,30 +41,30 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { private static final String NBT_PERIPHERAL_ENABLED = "PeripheralAccess"; private final WiredModemPeripheral[] modems = new WiredModemPeripheral[6]; - private final WiredModemLocalPeripheral[] m_peripherals = new WiredModemLocalPeripheral[6]; - private final ModemState m_modemState = new ModemState( () -> TickScheduler.schedule( this ) ); - private final WiredModemElement m_element = new FullElement( this ); - private final IWiredNode m_node = this.m_element.getNode(); - private boolean m_peripheralAccessAllowed = false; - private boolean m_destroyed = false; - private boolean m_connectionsFormed = false; + private final WiredModemLocalPeripheral[] peripherals = new WiredModemLocalPeripheral[6]; + private final ModemState modemState = new ModemState( () -> TickScheduler.schedule( this ) ); + private final WiredModemElement element = new FullElement( this ); + private final IWiredNode node = this.element.getNode(); + private boolean peripheralAccessAllowed = false; + private boolean destroyed = false; + private boolean connectionsFormed = false; public TileWiredModemFull( BlockEntityType type ) { super( type ); - for( int i = 0; i < this.m_peripherals.length; i++ ) + for( int i = 0; i < this.peripherals.length; i++ ) { Direction facing = Direction.byId( i ); - this.m_peripherals[i] = new WiredModemLocalPeripheral(); + this.peripherals[i] = new WiredModemLocalPeripheral(); } } @Override public void destroy() { - if( !this.m_destroyed ) + if( !this.destroyed ) { - this.m_destroyed = true; + this.destroyed = true; this.doRemove(); } super.destroy(); @@ -81,8 +81,8 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { if( this.world == null || !this.world.isClient ) { - this.m_node.remove(); - this.m_connectionsFormed = false; + this.node.remove(); + this.connectionsFormed = false; } } @@ -118,7 +118,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile @Override public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) { - if( !this.world.isClient && this.m_peripheralAccessAllowed ) + if( !this.world.isClient && this.peripheralAccessAllowed ) { for( Direction facing : DirectionUtil.FACINGS ) { @@ -139,21 +139,21 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile return; } - if( this.m_modemState.pollChanged() ) + if( this.modemState.pollChanged() ) { this.updateBlockState(); } - if( !this.m_connectionsFormed ) + if( !this.connectionsFormed ) { - this.m_connectionsFormed = true; + this.connectionsFormed = true; this.connectionsChanged(); - if( this.m_peripheralAccessAllowed ) + if( this.peripheralAccessAllowed ) { for( Direction facing : DirectionUtil.FACINGS ) { - this.m_peripherals[facing.ordinal()].attach( this.world, this.getPos(), facing ); + this.peripherals[facing.ordinal()].attach( this.world, this.getPos(), facing ); } this.updateConnectedPeripherals(); } @@ -183,13 +183,13 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile continue; } - this.m_node.connectTo( element.getNode() ); + this.node.connectTo( element.getNode() ); } } private void refreshPeripheral( @Nonnull Direction facing ) { - WiredModemLocalPeripheral peripheral = this.m_peripherals[facing.ordinal()]; + WiredModemLocalPeripheral peripheral = this.peripherals[facing.ordinal()]; if( this.world != null && !this.isRemoved() && peripheral.attach( this.world, this.getPos(), facing ) ) { this.updateConnectedPeripherals(); @@ -202,22 +202,22 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile if( peripherals.isEmpty() ) { // If there are no peripherals then disable access and update the display state. - this.m_peripheralAccessAllowed = false; + this.peripheralAccessAllowed = false; this.updateBlockState(); } - this.m_node.updatePeripherals( peripherals ); + this.node.updatePeripherals( peripherals ); } private Map getConnectedPeripherals() { - if( !this.m_peripheralAccessAllowed ) + if( !this.peripheralAccessAllowed ) { return Collections.emptyMap(); } Map peripherals = new HashMap<>( 6 ); - for( WiredModemLocalPeripheral peripheral : this.m_peripherals ) + for( WiredModemLocalPeripheral peripheral : this.peripherals ) { peripheral.extendMap( peripherals ); } @@ -227,7 +227,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile private void updateBlockState() { BlockState state = this.getCachedState(); - boolean modemOn = this.m_modemState.isOpen(), peripheralOn = this.m_peripheralAccessAllowed; + boolean modemOn = this.modemState.isOpen(), peripheralOn = this.peripheralAccessAllowed; if( state.get( MODEM_ON ) == modemOn && state.get( PERIPHERAL_ON ) == peripheralOn ) { return; @@ -240,13 +240,13 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile private Set getConnectedPeripheralNames() { - if( !this.m_peripheralAccessAllowed ) + if( !this.peripheralAccessAllowed ) { return Collections.emptySet(); } Set peripherals = new HashSet<>( 6 ); - for( WiredModemLocalPeripheral peripheral : this.m_peripherals ) + for( WiredModemLocalPeripheral peripheral : this.peripherals ) { String name = peripheral.getConnectedName(); if( name != null ) @@ -259,12 +259,12 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile private void togglePeripheralAccess() { - if( !this.m_peripheralAccessAllowed ) + if( !this.peripheralAccessAllowed ) { boolean hasAny = false; for( Direction facing : DirectionUtil.FACINGS ) { - WiredModemLocalPeripheral peripheral = this.m_peripherals[facing.ordinal()]; + WiredModemLocalPeripheral peripheral = this.peripherals[facing.ordinal()]; peripheral.attach( this.world, this.getPos(), facing ); hasAny |= peripheral.hasPeripheral(); } @@ -274,18 +274,18 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile return; } - this.m_peripheralAccessAllowed = true; - this.m_node.updatePeripherals( this.getConnectedPeripherals() ); + this.peripheralAccessAllowed = true; + this.node.updatePeripherals( this.getConnectedPeripherals() ); } else { - this.m_peripheralAccessAllowed = false; + this.peripheralAccessAllowed = false; - for( WiredModemLocalPeripheral peripheral : this.m_peripherals ) + for( WiredModemLocalPeripheral peripheral : this.peripherals ) { peripheral.detach(); } - this.m_node.updatePeripherals( Collections.emptyMap() ); + this.node.updatePeripherals( Collections.emptyMap() ); } this.updateBlockState(); @@ -318,10 +318,10 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) { super.fromTag( state, nbt ); - this.m_peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); - for( int i = 0; i < this.m_peripherals.length; i++ ) + this.peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); + for( int i = 0; i < this.peripherals.length; i++ ) { - this.m_peripherals[i].read( nbt, Integer.toString( i ) ); + this.peripherals[i].read( nbt, Integer.toString( i ) ); } } @@ -329,10 +329,10 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile @Override public CompoundTag toTag( CompoundTag nbt ) { - nbt.putBoolean( NBT_PERIPHERAL_ENABLED, this.m_peripheralAccessAllowed ); - for( int i = 0; i < this.m_peripherals.length; i++ ) + nbt.putBoolean( NBT_PERIPHERAL_ENABLED, this.peripheralAccessAllowed ); + for( int i = 0; i < this.peripherals.length; i++ ) { - this.m_peripherals[i].write( nbt, Integer.toString( i ) ); + this.peripherals[i].write( nbt, Integer.toString( i ) ); } return super.toTag( nbt ); } @@ -353,7 +353,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile public IWiredElement getElement() { - return this.m_element; + return this.element; } @Nonnull @@ -366,8 +366,8 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile return peripheral; } - WiredModemLocalPeripheral localPeripheral = this.m_peripherals[side.ordinal()]; - return this.modems[side.ordinal()] = new WiredModemPeripheral( this.m_modemState, this.m_element ) + WiredModemLocalPeripheral localPeripheral = this.peripherals[side.ordinal()]; + return this.modems[side.ordinal()] = new WiredModemPeripheral( this.modemState, this.element ) { @Nonnull @Override @@ -395,11 +395,11 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile private static final class FullElement extends WiredModemElement { - private final TileWiredModemFull m_entity; + private final TileWiredModemFull entity; private FullElement( TileWiredModemFull entity ) { - this.m_entity = entity; + this.entity = entity; } @Override @@ -407,7 +407,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { for( int i = 0; i < 6; i++ ) { - WiredModemPeripheral modem = this.m_entity.modems[i]; + WiredModemPeripheral modem = this.entity.modems[i]; if( modem != null ) { modem.detachPeripheral( name ); @@ -420,7 +420,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile { for( int i = 0; i < 6; i++ ) { - WiredModemPeripheral modem = this.m_entity.modems[i]; + WiredModemPeripheral modem = this.entity.modems[i]; if( modem != null ) { modem.attachPeripheral( name, peripheral ); @@ -432,14 +432,14 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile @Override public World getWorld() { - return this.m_entity.getWorld(); + return this.entity.getWorld(); } @Nonnull @Override public Vec3d getPosition() { - BlockPos pos = this.m_entity.getPos(); + BlockPos pos = this.entity.getPos(); return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java index 0d69b8e11..9350c21e5 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java @@ -15,18 +15,18 @@ import net.minecraft.world.World; public abstract class WirelessModemPeripheral extends ModemPeripheral { - private final boolean m_advanced; + private final boolean advanced; public WirelessModemPeripheral( ModemState state, boolean advanced ) { super( state ); - this.m_advanced = advanced; + this.advanced = advanced; } @Override public double getRange() { - if( this.m_advanced ) + if( this.advanced ) { return Integer.MAX_VALUE; } @@ -56,7 +56,7 @@ public abstract class WirelessModemPeripheral extends ModemPeripheral @Override public boolean isInterdimensional() { - return this.m_advanced; + return this.advanced; } @Override diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java index 4c0200ffe..e2466966a 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java @@ -19,35 +19,35 @@ import java.util.concurrent.ConcurrentHashMap; public class WirelessNetwork implements IPacketNetwork { - private static WirelessNetwork s_universalNetwork = null; - private final Set m_receivers = Collections.newSetFromMap( new ConcurrentHashMap<>() ); + private static WirelessNetwork universalNetwork = null; + private final Set receivers = Collections.newSetFromMap( new ConcurrentHashMap<>() ); public static WirelessNetwork getUniversal() { - if( s_universalNetwork == null ) + if( universalNetwork == null ) { - s_universalNetwork = new WirelessNetwork(); + universalNetwork = new WirelessNetwork(); } - return s_universalNetwork; + return universalNetwork; } public static void resetNetworks() { - s_universalNetwork = null; + universalNetwork = null; } @Override public void addReceiver( @Nonnull IPacketReceiver receiver ) { Objects.requireNonNull( receiver, "device cannot be null" ); - this.m_receivers.add( receiver ); + this.receivers.add( receiver ); } @Override public void removeReceiver( @Nonnull IPacketReceiver receiver ) { Objects.requireNonNull( receiver, "device cannot be null" ); - this.m_receivers.remove( receiver ); + this.receivers.remove( receiver ); } @Override @@ -60,7 +60,7 @@ public class WirelessNetwork implements IPacketNetwork public void transmitSameDimension( @Nonnull Packet packet, double range ) { Objects.requireNonNull( packet, "packet cannot be null" ); - for( IPacketReceiver device : this.m_receivers ) + for( IPacketReceiver device : this.receivers ) { tryTransmit( device, packet, range, false ); } @@ -70,7 +70,7 @@ public class WirelessNetwork implements IPacketNetwork public void transmitInterdimensional( @Nonnull Packet packet ) { Objects.requireNonNull( packet, "packet cannot be null" ); - for( IPacketReceiver device : this.m_receivers ) + for( IPacketReceiver device : this.receivers ) { tryTransmit( device, packet, 0, true ); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java index ee328608c..fca06c392 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java @@ -43,20 +43,20 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile private static final String NBT_HEIGHT = "Height"; private final boolean advanced; - private final Set m_computers = new HashSet<>(); + private final Set computers = new HashSet<>(); // MonitorWatcher state. boolean enqueued; TerminalState cached; - private ServerMonitor m_serverMonitor; - private ClientMonitor m_clientMonitor; + private ServerMonitor serverMonitor; + private ClientMonitor clientMonitor; private MonitorPeripheral peripheral; private boolean needsUpdate = false; - private boolean m_destroyed = false; + private boolean destroyed = false; private boolean visiting = false; - private int m_width = 1; - private int m_height = 1; - private int m_xIndex = 0; - private int m_yIndex = 0; + private int width = 1; + private int height = 1; + private int xIndex = 0; + private int yIndex = 0; public TileMonitor( BlockEntityType type, boolean advanced ) { @@ -68,11 +68,11 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile public void destroy() { // TODO: Call this before using the block - if( this.m_destroyed ) + if( this.destroyed ) { return; } - this.m_destroyed = true; + this.destroyed = true; if( !this.getWorld().isClient ) { this.contractNeighbours(); @@ -83,9 +83,9 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile public void markRemoved() { super.markRemoved(); - if( this.m_clientMonitor != null && this.m_xIndex == 0 && this.m_yIndex == 0 ) + if( this.clientMonitor != null && this.xIndex == 0 && this.yIndex == 0 ) { - this.m_clientMonitor.destroy(); + this.clientMonitor.destroy(); } } @@ -93,11 +93,11 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile public void onChunkUnloaded() { super.onChunkUnloaded(); - if( this.m_clientMonitor != null && this.m_xIndex == 0 && this.m_yIndex == 0 ) + if( this.clientMonitor != null && this.xIndex == 0 && this.yIndex == 0 ) { - this.m_clientMonitor.destroy(); + this.clientMonitor.destroy(); } - this.m_clientMonitor = null; + this.clientMonitor = null; } @Nonnull @@ -130,18 +130,18 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile updateNeighbors(); } - if( this.m_xIndex != 0 || this.m_yIndex != 0 || this.m_serverMonitor == null ) + if( this.xIndex != 0 || this.yIndex != 0 || this.serverMonitor == null ) { return; } - this.m_serverMonitor.clearChanged(); + this.serverMonitor.clearChanged(); - if( this.m_serverMonitor.pollResized() ) + if( this.serverMonitor.pollResized() ) { - for( int x = 0; x < this.m_width; x++ ) + for( int x = 0; x < this.width; x++ ) { - for( int y = 0; y < this.m_height; y++ ) + for( int y = 0; y < this.height; y++ ) { TileMonitor monitor = this.getNeighbour( x, y ); if( monitor == null ) @@ -149,7 +149,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile continue; } - for( IComputerAccess computer : monitor.m_computers ) + for( IComputerAccess computer : monitor.computers ) { computer.queueEvent( "monitor_resize", computer.getAttachmentName() ); } @@ -157,7 +157,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile } } - if( this.m_serverMonitor.pollTerminalChanged() ) + if( this.serverMonitor.pollTerminalChanged() ) { this.updateBlock(); } @@ -168,38 +168,38 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { super.readDescription( nbt ); - int oldXIndex = this.m_xIndex; - int oldYIndex = this.m_yIndex; - int oldWidth = this.m_width; - int oldHeight = this.m_height; + int oldXIndex = this.xIndex; + int oldYIndex = this.yIndex; + int oldWidth = this.width; + int oldHeight = this.height; - this.m_xIndex = nbt.getInt( NBT_X ); - this.m_yIndex = nbt.getInt( NBT_Y ); - this.m_width = nbt.getInt( NBT_WIDTH ); - this.m_height = nbt.getInt( NBT_HEIGHT ); + this.xIndex = nbt.getInt( NBT_X ); + this.yIndex = nbt.getInt( NBT_Y ); + this.width = nbt.getInt( NBT_WIDTH ); + this.height = nbt.getInt( NBT_HEIGHT ); - if( oldXIndex != this.m_xIndex || oldYIndex != this.m_yIndex ) + if( oldXIndex != this.xIndex || oldYIndex != this.yIndex ) { // If our index has changed then it's possible the origin monitor has changed. Thus // we'll clear our cache. If we're the origin then we'll need to remove the glList as well. - if( oldXIndex == 0 && oldYIndex == 0 && this.m_clientMonitor != null ) + if( oldXIndex == 0 && oldYIndex == 0 && this.clientMonitor != null ) { - this.m_clientMonitor.destroy(); + this.clientMonitor.destroy(); } - this.m_clientMonitor = null; + this.clientMonitor = null; } - if( this.m_xIndex == 0 && this.m_yIndex == 0 ) + if( this.xIndex == 0 && this.yIndex == 0 ) { // If we're the origin terminal then create it. - if( this.m_clientMonitor == null ) + if( this.clientMonitor == null ) { - this.m_clientMonitor = new ClientMonitor( this.advanced, this ); + this.clientMonitor = new ClientMonitor( this.advanced, this ); } - this.m_clientMonitor.readDescription( nbt ); + this.clientMonitor.readDescription( nbt ); } - if( oldXIndex != this.m_xIndex || oldYIndex != this.m_yIndex || oldWidth != this.m_width || oldHeight != this.m_height ) + if( oldXIndex != this.xIndex || oldYIndex != this.yIndex || oldWidth != this.width || oldHeight != this.height ) { // One of our properties has changed, so ensure we redraw the block this.updateBlock(); @@ -210,14 +210,14 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile protected void writeDescription( @Nonnull CompoundTag nbt ) { super.writeDescription( nbt ); - nbt.putInt( NBT_X, this.m_xIndex ); - nbt.putInt( NBT_Y, this.m_yIndex ); - nbt.putInt( NBT_WIDTH, this.m_width ); - nbt.putInt( NBT_HEIGHT, this.m_height ); + nbt.putInt( NBT_X, this.xIndex ); + nbt.putInt( NBT_Y, this.yIndex ); + nbt.putInt( NBT_WIDTH, this.width ); + nbt.putInt( NBT_HEIGHT, this.height ); - if( this.m_xIndex == 0 && this.m_yIndex == 0 && this.m_serverMonitor != null ) + if( this.xIndex == 0 && this.yIndex == 0 && this.serverMonitor != null ) { - this.m_serverMonitor.writeDescription( nbt ); + this.serverMonitor.writeDescription( nbt ); } } @@ -226,8 +226,8 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile BlockPos pos = this.getPos(); Direction right = this.getRight(); Direction down = this.getDown(); - int xOffset = -this.m_xIndex + x; - int yOffset = -this.m_yIndex + y; + int xOffset = -this.xIndex + x; + int yOffset = -this.yIndex + y; return this.getSimilarMonitorAt( pos.offset( right, xOffset ) .offset( down, yOffset ) ); } @@ -268,7 +268,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile } TileMonitor monitor = (TileMonitor) tile; - return !monitor.visiting && !monitor.m_destroyed && this.advanced == monitor.advanced && this.getDirection() == monitor.getDirection() && this.getOrientation() == monitor.getOrientation() ? monitor : null; + return !monitor.visiting && !monitor.destroyed && this.advanced == monitor.advanced && this.getDirection() == monitor.getDirection() && this.getOrientation() == monitor.getOrientation() ? monitor : null; } // region Sizing and placement stuff @@ -290,10 +290,10 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile { super.fromTag( state, nbt ); - this.m_xIndex = nbt.getInt( NBT_X ); - this.m_yIndex = nbt.getInt( NBT_Y ); - this.m_width = nbt.getInt( NBT_WIDTH ); - this.m_height = nbt.getInt( NBT_HEIGHT ); + this.xIndex = nbt.getInt( NBT_X ); + this.yIndex = nbt.getInt( NBT_Y ); + this.width = nbt.getInt( NBT_WIDTH ); + this.height = nbt.getInt( NBT_HEIGHT ); } // Networking stuff @@ -302,10 +302,10 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile @Override public CompoundTag toTag( CompoundTag tag ) { - tag.putInt( NBT_X, this.m_xIndex ); - tag.putInt( NBT_Y, this.m_yIndex ); - tag.putInt( NBT_WIDTH, this.m_width ); - tag.putInt( NBT_HEIGHT, this.m_height ); + tag.putInt( NBT_X, this.xIndex ); + tag.putInt( NBT_Y, this.yIndex ); + tag.putInt( NBT_WIDTH, this.width ); + tag.putInt( NBT_HEIGHT, this.height ); return super.toTag( tag ); } @@ -338,14 +338,14 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile public ServerMonitor getCachedServerMonitor() { - return this.m_serverMonitor; + return this.serverMonitor; } private ServerMonitor getServerMonitor() { - if( this.m_serverMonitor != null ) + if( this.serverMonitor != null ) { - return this.m_serverMonitor; + return this.serverMonitor; } TileMonitor origin = this.getOrigin(); @@ -354,92 +354,92 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile return null; } - return this.m_serverMonitor = origin.m_serverMonitor; + return this.serverMonitor = origin.serverMonitor; } private ServerMonitor createServerMonitor() { - if( this.m_serverMonitor != null ) + if( this.serverMonitor != null ) { - return this.m_serverMonitor; + return this.serverMonitor; } - if( this.m_xIndex == 0 && this.m_yIndex == 0 ) + if( this.xIndex == 0 && this.yIndex == 0 ) { // If we're the origin, set up the new monitor - this.m_serverMonitor = new ServerMonitor( this.advanced, this ); - this.m_serverMonitor.rebuild(); + this.serverMonitor = new ServerMonitor( this.advanced, this ); + this.serverMonitor.rebuild(); // And propagate it to child monitors - for( int x = 0; x < this.m_width; x++ ) + for( int x = 0; x < this.width; x++ ) { - for( int y = 0; y < this.m_height; y++ ) + for( int y = 0; y < this.height; y++ ) { TileMonitor monitor = this.getNeighbour( x, y ); if( monitor != null ) { - monitor.m_serverMonitor = this.m_serverMonitor; + monitor.serverMonitor = this.serverMonitor; } } } - return this.m_serverMonitor; + return this.serverMonitor; } else { // Otherwise fetch the origin and attempt to get its monitor // Note this may load chunks, but we don't really have a choice here. BlockPos pos = this.getPos(); - BlockEntity te = this.world.getBlockEntity( pos.offset( this.getRight(), -this.m_xIndex ) - .offset( this.getDown(), -this.m_yIndex ) ); + BlockEntity te = this.world.getBlockEntity( pos.offset( this.getRight(), -this.xIndex ) + .offset( this.getDown(), -this.yIndex ) ); if( !(te instanceof TileMonitor) ) { return null; } - return this.m_serverMonitor = ((TileMonitor) te).createServerMonitor(); + return this.serverMonitor = ((TileMonitor) te).createServerMonitor(); } } public ClientMonitor getClientMonitor() { - if( this.m_clientMonitor != null ) + if( this.clientMonitor != null ) { - return this.m_clientMonitor; + return this.clientMonitor; } BlockPos pos = this.getPos(); - BlockEntity te = this.world.getBlockEntity( pos.offset( this.getRight(), -this.m_xIndex ) - .offset( this.getDown(), -this.m_yIndex ) ); + BlockEntity te = this.world.getBlockEntity( pos.offset( this.getRight(), -this.xIndex ) + .offset( this.getDown(), -this.yIndex ) ); if( !(te instanceof TileMonitor) ) { return null; } - return this.m_clientMonitor = ((TileMonitor) te).m_clientMonitor; + return this.clientMonitor = ((TileMonitor) te).clientMonitor; } public final void read( TerminalState state ) { - if( this.m_xIndex != 0 || this.m_yIndex != 0 ) + if( this.xIndex != 0 || this.yIndex != 0 ) { ComputerCraft.log.warn( "Receiving monitor state for non-origin terminal at {}", this.getPos() ); return; } - if( this.m_clientMonitor == null ) + if( this.clientMonitor == null ) { - this.m_clientMonitor = new ClientMonitor( this.advanced, this ); + this.clientMonitor = new ClientMonitor( this.advanced, this ); } - this.m_clientMonitor.read( state ); + this.clientMonitor.read( state ); } private void updateBlockState() { this.getWorld().setBlockState( this.getPos(), this.getCachedState().with( BlockMonitor.STATE, - MonitorEdgeState.fromConnections( this.m_yIndex < this.m_height - 1, - this.m_yIndex > 0, this.m_xIndex > 0, this.m_xIndex < this.m_width - 1 ) ), + MonitorEdgeState.fromConnections( this.yIndex < this.height - 1, + this.yIndex > 0, this.xIndex > 0, this.xIndex < this.width - 1 ) ), 2 ); } @@ -451,22 +451,22 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile public int getWidth() { - return this.m_width; + return this.width; } public int getHeight() { - return this.m_height; + return this.height; } public int getXIndex() { - return this.m_xIndex; + return this.xIndex; } public int getYIndex() { - return this.m_yIndex; + return this.yIndex; } private TileMonitor getOrigin() @@ -477,15 +477,15 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile private void resize( int width, int height ) { // If we're not already the origin then we'll need to generate a new terminal. - if( this.m_xIndex != 0 || this.m_yIndex != 0 ) + if( this.xIndex != 0 || this.yIndex != 0 ) { - this.m_serverMonitor = null; + this.serverMonitor = null; } - this.m_xIndex = 0; - this.m_yIndex = 0; - this.m_width = width; - this.m_height = height; + this.xIndex = 0; + this.yIndex = 0; + this.width = width; + this.height = height; // Determine if we actually need a monitor. In order to do this, simply check if // any component monitor been wrapped as a peripheral. Whilst this flag may be @@ -508,21 +508,21 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile // Either delete the current monitor or sync a new one. if( needsTerminal ) { - if( this.m_serverMonitor == null ) + if( this.serverMonitor == null ) { - this.m_serverMonitor = new ServerMonitor( this.advanced, this ); + this.serverMonitor = new ServerMonitor( this.advanced, this ); } } else { - this.m_serverMonitor = null; + this.serverMonitor = null; } // Update the terminal's width and height and rebuild it. This ensures the monitor // is consistent when syncing it to other monitors. - if( this.m_serverMonitor != null ) + if( this.serverMonitor != null ) { - this.m_serverMonitor.rebuild(); + this.serverMonitor.rebuild(); } // Update the other monitors, setting coordinates, dimensions and the server terminal @@ -536,11 +536,11 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile continue; } - monitor.m_xIndex = x; - monitor.m_yIndex = y; - monitor.m_width = width; - monitor.m_height = height; - monitor.m_serverMonitor = this.m_serverMonitor; + monitor.xIndex = x; + monitor.yIndex = y; + monitor.width = width; + monitor.height = height; + monitor.serverMonitor = this.serverMonitor; monitor.updateBlockState(); monitor.updateBlock(); } @@ -550,12 +550,12 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile private boolean mergeLeft() { TileMonitor left = this.getNeighbour( -1, 0 ); - if( left == null || left.m_yIndex != 0 || left.m_height != this.m_height ) + if( left == null || left.yIndex != 0 || left.height != this.height ) { return false; } - int width = left.m_width + this.m_width; + int width = left.width + this.width; if( width > ComputerCraft.monitorWidth ) { return false; @@ -564,7 +564,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile TileMonitor origin = left.getOrigin(); if( origin != null ) { - origin.resize( width, this.m_height ); + origin.resize( width, this.height ); } left.expand(); return true; @@ -572,13 +572,13 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile private boolean mergeRight() { - TileMonitor right = this.getNeighbour( this.m_width, 0 ); - if( right == null || right.m_yIndex != 0 || right.m_height != this.m_height ) + TileMonitor right = this.getNeighbour( this.width, 0 ); + if( right == null || right.yIndex != 0 || right.height != this.height ) { return false; } - int width = this.m_width + right.m_width; + int width = this.width + right.width; if( width > ComputerCraft.monitorWidth ) { return false; @@ -587,7 +587,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile TileMonitor origin = this.getOrigin(); if( origin != null ) { - origin.resize( width, this.m_height ); + origin.resize( width, this.height ); } this.expand(); return true; @@ -595,13 +595,13 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile private boolean mergeUp() { - TileMonitor above = this.getNeighbour( 0, this.m_height ); - if( above == null || above.m_xIndex != 0 || above.m_width != this.m_width ) + TileMonitor above = this.getNeighbour( 0, this.height ); + if( above == null || above.xIndex != 0 || above.width != this.width ) { return false; } - int height = above.m_height + this.m_height; + int height = above.height + this.height; if( height > ComputerCraft.monitorHeight ) { return false; @@ -610,7 +610,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile TileMonitor origin = this.getOrigin(); if( origin != null ) { - origin.resize( this.m_width, height ); + origin.resize( this.width, height ); } this.expand(); return true; @@ -619,12 +619,12 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile private boolean mergeDown() { TileMonitor below = this.getNeighbour( 0, -1 ); - if( below == null || below.m_xIndex != 0 || below.m_width != this.m_width ) + if( below == null || below.xIndex != 0 || below.width != this.width ) { return false; } - int height = this.m_height + below.m_height; + int height = this.height + below.height; if( height > ComputerCraft.monitorHeight ) { return false; @@ -633,7 +633,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile TileMonitor origin = below.getOrigin(); if( origin != null ) { - origin.resize( this.m_width, height ); + origin.resize( this.width, height ); } below.expand(); return true; @@ -662,33 +662,33 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile void contractNeighbours() { this.visiting = true; - if( this.m_xIndex > 0 ) + if( this.xIndex > 0 ) { - TileMonitor left = this.getNeighbour( this.m_xIndex - 1, this.m_yIndex ); + TileMonitor left = this.getNeighbour( this.xIndex - 1, this.yIndex ); if( left != null ) { left.contract(); } } - if( this.m_xIndex + 1 < this.m_width ) + if( this.xIndex + 1 < this.width ) { - TileMonitor right = this.getNeighbour( this.m_xIndex + 1, this.m_yIndex ); + TileMonitor right = this.getNeighbour( this.xIndex + 1, this.yIndex ); if( right != null ) { right.contract(); } } - if( this.m_yIndex > 0 ) + if( this.yIndex > 0 ) { - TileMonitor below = this.getNeighbour( this.m_xIndex, this.m_yIndex - 1 ); + TileMonitor below = this.getNeighbour( this.xIndex, this.yIndex - 1 ); if( below != null ) { below.contract(); } } - if( this.m_yIndex + 1 < this.m_height ) + if( this.yIndex + 1 < this.height ) { - TileMonitor above = this.getNeighbour( this.m_xIndex, this.m_yIndex + 1 ); + TileMonitor above = this.getNeighbour( this.xIndex, this.yIndex + 1 ); if( above != null ) { above.contract(); @@ -699,8 +699,8 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile void contract() { - int height = this.m_height; - int width = this.m_width; + int height = this.height; + int width = this.width; TileMonitor origin = this.getOrigin(); if( origin == null ) @@ -791,9 +791,9 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile private void monitorTouched( float xPos, float yPos, float zPos ) { XYPair pair = XYPair.of( xPos, yPos, zPos, this.getDirection(), this.getOrientation() ) - .add( this.m_xIndex, this.m_height - this.m_yIndex - 1 ); + .add( this.xIndex, this.height - this.yIndex - 1 ); - if( pair.x > this.m_width - RENDER_BORDER || pair.y > this.m_height - RENDER_BORDER || pair.x < RENDER_BORDER || pair.y < RENDER_BORDER ) + if( pair.x > this.width - RENDER_BORDER || pair.y > this.height - RENDER_BORDER || pair.x < RENDER_BORDER || pair.y < RENDER_BORDER ) { return; } @@ -810,15 +810,15 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile return; } - double xCharWidth = (this.m_width - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getWidth(); - double yCharHeight = (this.m_height - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getHeight(); + double xCharWidth = (this.width - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getWidth(); + double yCharHeight = (this.height - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getHeight(); int xCharPos = (int) Math.min( originTerminal.getWidth(), Math.max( (pair.x - RENDER_BORDER - RENDER_MARGIN) / xCharWidth + 1.0, 1.0 ) ); int yCharPos = (int) Math.min( originTerminal.getHeight(), Math.max( (pair.y - RENDER_BORDER - RENDER_MARGIN) / yCharHeight + 1.0, 1.0 ) ); - for( int y = 0; y < this.m_height; y++ ) + for( int y = 0; y < this.height; y++ ) { - for( int x = 0; x < this.m_width; x++ ) + for( int x = 0; x < this.width; x++ ) { TileMonitor monitor = this.getNeighbour( x, y ); if( monitor == null ) @@ -826,7 +826,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile continue; } - for( IComputerAccess computer : monitor.m_computers ) + for( IComputerAccess computer : monitor.computers ) { computer.queueEvent( "monitor_touch", computer.getAttachmentName(), xCharPos, yCharPos ); } @@ -836,7 +836,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile void addComputer( IComputerAccess computer ) { - this.m_computers.add( computer ); + this.computers.add( computer ); } // @Nonnull @@ -866,6 +866,6 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile void removeComputer( IComputerAccess computer ) { - this.m_computers.remove( computer ); + this.computers.remove( computer ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java index a5198248d..32afe0839 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -63,12 +63,12 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent 6 }; private static final int[] SIDE_SLOTS = new int[] { 0 }; - private final DefaultedList m_inventory = DefaultedList.ofSize( SLOTS, ItemStack.EMPTY ); - private final ItemStorage m_itemHandlerAll = ItemStorage.wrap( this ); - private final Terminal m_page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE ); + private final DefaultedList inventory = DefaultedList.ofSize( SLOTS, ItemStack.EMPTY ); + private final ItemStorage itemHandlerAll = ItemStorage.wrap( this ); + private final Terminal page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE ); Text customName; - private String m_pageTitle = ""; - private boolean m_printing = false; + private String pageTitle = ""; + private boolean printing = false; public TilePrinter( BlockEntityType type ) { @@ -101,7 +101,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent { for( int i = 0; i < 13; i++ ) { - ItemStack stack = this.m_inventory.get( i ); + ItemStack stack = this.inventory.get( i ); if( !stack.isEmpty() ) { // Remove the stack from the inventory @@ -120,7 +120,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent boolean top = false, bottom = false; for( int i = 1; i < 7; i++ ) { - ItemStack stack = this.m_inventory.get( i ); + ItemStack stack = this.inventory.get( i ); if( !stack.isEmpty() && isPaper( stack ) ) { top = true; @@ -129,7 +129,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } for( int i = 7; i < 13; i++ ) { - ItemStack stack = this.m_inventory.get( i ); + ItemStack stack = this.inventory.get( i ); if( !stack.isEmpty() && isPaper( stack ) ) { bottom = true; @@ -172,15 +172,15 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent this.customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; // Read page - synchronized( this.m_page ) + synchronized( this.page ) { - this.m_printing = nbt.getBoolean( NBT_PRINTING ); - this.m_pageTitle = nbt.getString( NBT_PAGE_TITLE ); - this.m_page.readFromNBT( nbt ); + this.printing = nbt.getBoolean( NBT_PRINTING ); + this.pageTitle = nbt.getString( NBT_PAGE_TITLE ); + this.page.readFromNBT( nbt ); } // Read inventory - Inventories.fromTag( nbt, this.m_inventory ); + Inventories.fromTag( nbt, this.inventory ); } @Nonnull @@ -193,35 +193,35 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } // Write page - synchronized( this.m_page ) + synchronized( this.page ) { - nbt.putBoolean( NBT_PRINTING, this.m_printing ); - nbt.putString( NBT_PAGE_TITLE, this.m_pageTitle ); - this.m_page.writeToNBT( nbt ); + nbt.putBoolean( NBT_PRINTING, this.printing ); + nbt.putString( NBT_PAGE_TITLE, this.pageTitle ); + this.page.writeToNBT( nbt ); } // Write inventory - Inventories.toTag( nbt, this.m_inventory ); + Inventories.toTag( nbt, this.inventory ); return super.toTag( nbt ); } boolean isPrinting() { - return this.m_printing; + return this.printing; } // IInventory implementation @Override public int size() { - return this.m_inventory.size(); + return this.inventory.size(); } @Override public boolean isEmpty() { - for( ItemStack stack : this.m_inventory ) + for( ItemStack stack : this.inventory ) { if( !stack.isEmpty() ) { @@ -235,14 +235,14 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Override public ItemStack getStack( int slot ) { - return this.m_inventory.get( slot ); + return this.inventory.get( slot ); } @Nonnull @Override public ItemStack removeStack( int slot, int count ) { - ItemStack stack = this.m_inventory.get( slot ); + ItemStack stack = this.inventory.get( slot ); if( stack.isEmpty() ) { return ItemStack.EMPTY; @@ -255,10 +255,10 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } ItemStack part = stack.split( count ); - if( this.m_inventory.get( slot ) + if( this.inventory.get( slot ) .isEmpty() ) { - this.m_inventory.set( slot, ItemStack.EMPTY ); + this.inventory.set( slot, ItemStack.EMPTY ); this.updateBlockState(); } this.markDirty(); @@ -269,8 +269,8 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Override public ItemStack removeStack( int slot ) { - ItemStack result = this.m_inventory.get( slot ); - this.m_inventory.set( slot, ItemStack.EMPTY ); + ItemStack result = this.inventory.get( slot ); + this.inventory.set( slot, ItemStack.EMPTY ); this.markDirty(); this.updateBlockState(); return result; @@ -281,7 +281,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Override public void setStack( int slot, @Nonnull ItemStack stack ) { - this.m_inventory.set( slot, stack ); + this.inventory.set( slot, stack ); this.markDirty(); this.updateBlockState(); } @@ -295,9 +295,9 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Override public void clear() { - for( int i = 0; i < this.m_inventory.size(); i++ ) + for( int i = 0; i < this.inventory.size(); i++ ) { - this.m_inventory.set( i, ItemStack.EMPTY ); + this.inventory.set( i, ItemStack.EMPTY ); } this.markDirty(); this.updateBlockState(); @@ -350,21 +350,21 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Nullable Terminal getCurrentPage() { - synchronized( this.m_page ) + synchronized( this.page ) { - return this.m_printing ? this.m_page : null; + return this.printing ? this.page : null; } } boolean startNewPage() { - synchronized( this.m_page ) + synchronized( this.page ) { if( !this.canInputPage() ) { return false; } - if( this.m_printing && !this.outputPage() ) + if( this.printing && !this.outputPage() ) { return false; } @@ -374,33 +374,33 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent boolean endCurrentPage() { - synchronized( this.m_page ) + synchronized( this.page ) { - return this.m_printing && this.outputPage(); + return this.printing && this.outputPage(); } } private boolean outputPage() { - int height = this.m_page.getHeight(); + int height = this.page.getHeight(); String[] lines = new String[height]; String[] colours = new String[height]; for( int i = 0; i < height; i++ ) { - lines[i] = this.m_page.getLine( i ) + lines[i] = this.page.getLine( i ) .toString(); - colours[i] = this.m_page.getTextColourLine( i ) + colours[i] = this.page.getTextColourLine( i ) .toString(); } - ItemStack stack = ItemPrintout.createSingleFromTitleAndText( this.m_pageTitle, lines, colours ); + ItemStack stack = ItemPrintout.createSingleFromTitleAndText( this.pageTitle, lines, colours ); for( int slot : BOTTOM_SLOTS ) { - if( this.m_inventory.get( slot ) + if( this.inventory.get( slot ) .isEmpty() ) { this.setStack( slot, stack ); - this.m_printing = false; + this.printing = false; return true; } } @@ -409,7 +409,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent int getInkLevel() { - ItemStack inkStack = this.m_inventory.get( 0 ); + ItemStack inkStack = this.inventory.get( 0 ); return isInk( inkStack ) ? inkStack.getCount() : 0; } @@ -418,7 +418,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent int count = 0; for( int i = 1; i < 7; i++ ) { - ItemStack paperStack = this.m_inventory.get( i ); + ItemStack paperStack = this.inventory.get( i ); if( isPaper( paperStack ) ) { count += paperStack.getCount(); @@ -429,72 +429,72 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent void setPageTitle( String title ) { - synchronized( this.m_page ) + synchronized( this.page ) { - if( this.m_printing ) + if( this.printing ) { - this.m_pageTitle = title; + this.pageTitle = title; } } } private boolean canInputPage() { - ItemStack inkStack = this.m_inventory.get( 0 ); + ItemStack inkStack = this.inventory.get( 0 ); return !inkStack.isEmpty() && isInk( inkStack ) && this.getPaperLevel() > 0; } private boolean inputPage() { - ItemStack inkStack = this.m_inventory.get( 0 ); + ItemStack inkStack = this.inventory.get( 0 ); DyeColor dye = ColourUtils.getStackColour( inkStack ); if( dye == null ) return false; for( int i = 1; i < 7; i++ ) { - ItemStack paperStack = this.m_inventory.get( i ); + ItemStack paperStack = this.inventory.get( i ); if( paperStack.isEmpty() || !isPaper( paperStack ) ) { continue; } // Setup the new page - m_page.setTextColour( dye.getId() ); + page.setTextColour( dye.getId() ); - this.m_page.clear(); + this.page.clear(); if( paperStack.getItem() instanceof ItemPrintout ) { - this.m_pageTitle = ItemPrintout.getTitle( paperStack ); + this.pageTitle = ItemPrintout.getTitle( paperStack ); String[] text = ItemPrintout.getText( paperStack ); String[] textColour = ItemPrintout.getColours( paperStack ); - for( int y = 0; y < this.m_page.getHeight(); y++ ) + for( int y = 0; y < this.page.getHeight(); y++ ) { - this.m_page.setLine( y, text[y], textColour[y], "" ); + this.page.setLine( y, text[y], textColour[y], "" ); } } else { - this.m_pageTitle = ""; + this.pageTitle = ""; } - this.m_page.setCursorPos( 0, 0 ); + this.page.setCursorPos( 0, 0 ); // Decrement ink inkStack.decrement( 1 ); if( inkStack.isEmpty() ) { - this.m_inventory.set( 0, ItemStack.EMPTY ); + this.inventory.set( 0, ItemStack.EMPTY ); } // Decrement paper paperStack.decrement( 1 ); if( paperStack.isEmpty() ) { - this.m_inventory.set( i, ItemStack.EMPTY ); + this.inventory.set( i, ItemStack.EMPTY ); this.updateBlockState(); } this.markDirty(); - this.m_printing = true; + this.printing = true; return true; } return false; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java index 2e9ffe3b5..72d45ba85 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java @@ -34,19 +34,19 @@ import static dan200.computercraft.api.lua.LuaValues.checkFinite; */ public abstract class SpeakerPeripheral implements IPeripheral { - private final AtomicInteger m_notesThisTick = new AtomicInteger(); - private long m_clock = 0; - private long m_lastPlayTime = 0; + private final AtomicInteger notesThisTick = new AtomicInteger(); + private long clock = 0; + private long lastPlayTime = 0; public void update() { - this.m_clock++; - this.m_notesThisTick.set( 0 ); + this.clock++; + this.notesThisTick.set( 0 ); } public boolean madeSound( long ticks ) { - return this.m_clock - this.m_lastPlayTime <= ticks; + return this.clock - this.lastPlayTime <= ticks; } @Nonnull @@ -90,7 +90,7 @@ public abstract class SpeakerPeripheral implements IPeripheral private synchronized boolean playSound( ILuaContext context, Identifier name, float volume, float pitch, boolean isNote ) throws LuaException { - if( this.m_clock - this.m_lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS && (!isNote || this.m_clock - this.m_lastPlayTime != 0 || this.m_notesThisTick.get() >= ComputerCraft.maxNotesPerTick) ) + if( this.clock - this.lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS && (!isNote || this.clock - this.lastPlayTime != 0 || this.notesThisTick.get() >= ComputerCraft.maxNotesPerTick) ) { // Rate limiting occurs when we've already played a sound within the last tick, or we've // played more notes than allowable within the current tick. @@ -119,7 +119,7 @@ public abstract class SpeakerPeripheral implements IPeripheral return null; } ); - this.m_lastPlayTime = this.m_clock; + this.lastPlayTime = this.clock; return true; } @@ -173,7 +173,7 @@ public abstract class SpeakerPeripheral implements IPeripheral true ); if( success ) { - this.m_notesThisTick.incrementAndGet(); + this.notesThisTick.incrementAndGet(); } return success; } diff --git a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java index bc28daa9a..af090de6a 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java @@ -36,9 +36,9 @@ import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LI public class PocketServerComputer extends ServerComputer implements IPocketAccess { - private IPocketUpgrade m_upgrade; - private Entity m_entity; - private ItemStack m_stack; + private IPocketUpgrade upgrade; + private Entity entity; + private ItemStack stack; public PocketServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family ) { @@ -49,8 +49,8 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces @Override public Entity getEntity() { - Entity entity = this.m_entity; - if( entity == null || this.m_stack == null || !entity.isAlive() ) + Entity entity = this.entity; + if( entity == null || this.stack == null || !entity.isAlive() ) { return null; } @@ -58,12 +58,12 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces if( entity instanceof PlayerEntity ) { PlayerInventory inventory = ((PlayerEntity) entity).inventory; - return inventory.main.contains( this.m_stack ) || inventory.offHand.contains( this.m_stack ) ? entity : null; + return inventory.main.contains( this.stack ) || inventory.offHand.contains( this.stack ) ? entity : null; } else if( entity instanceof LivingEntity ) { LivingEntity living = (LivingEntity) entity; - return living.getMainHandStack() == this.m_stack || living.getOffHandStack() == this.m_stack ? entity : null; + return living.getMainHandStack() == this.stack || living.getOffHandStack() == this.stack ? entity : null; } else { @@ -74,13 +74,13 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces @Override public int getColour() { - return IColouredItem.getColourBasic( this.m_stack ); + return IColouredItem.getColourBasic( this.stack ); } @Override public void setColour( int colour ) { - IColouredItem.setColourBasic( this.m_stack, colour ); + IColouredItem.setColourBasic( this.stack, colour ); this.updateUpgradeNBTData(); } @@ -114,22 +114,22 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces @Override public CompoundTag getUpgradeNBTData() { - return ItemPocketComputer.getUpgradeInfo( this.m_stack ); + return ItemPocketComputer.getUpgradeInfo( this.stack ); } @Override public void updateUpgradeNBTData() { - if( this.m_entity instanceof PlayerEntity ) + if( this.entity instanceof PlayerEntity ) { - ((PlayerEntity) this.m_entity).inventory.markDirty(); + ((PlayerEntity) this.entity).inventory.markDirty(); } } @Override public void invalidatePeripheral() { - IPeripheral peripheral = this.m_upgrade == null ? null : this.m_upgrade.createPeripheral( this ); + IPeripheral peripheral = this.upgrade == null ? null : this.upgrade.createPeripheral( this ); this.setPeripheral( ComputerSide.BACK, peripheral ); } @@ -137,12 +137,12 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces @Override public Map getUpgrades() { - return this.m_upgrade == null ? Collections.emptyMap() : Collections.singletonMap( this.m_upgrade.getUpgradeID(), this.getPeripheral( ComputerSide.BACK ) ); + return this.upgrade == null ? Collections.emptyMap() : Collections.singletonMap( this.upgrade.getUpgradeID(), this.getPeripheral( ComputerSide.BACK ) ); } public IPocketUpgrade getUpgrade() { - return this.m_upgrade; + return this.upgrade; } /** @@ -154,16 +154,16 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces */ public void setUpgrade( IPocketUpgrade upgrade ) { - if( this.m_upgrade == upgrade ) + if( this.upgrade == upgrade ) { return; } synchronized( this ) { - ItemPocketComputer.setUpgrade( this.m_stack, upgrade ); + ItemPocketComputer.setUpgrade( this.stack, upgrade ); this.updateUpgradeNBTData(); - this.m_upgrade = upgrade; + this.upgrade = upgrade; this.invalidatePeripheral(); } } @@ -177,17 +177,17 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces } // If a new entity has picked it up then rebroadcast the terminal to them - if( entity != this.m_entity && entity instanceof ServerPlayerEntity ) + if( entity != this.entity && entity instanceof ServerPlayerEntity ) { this.markTerminalChanged(); } - this.m_entity = entity; - this.m_stack = stack; + this.entity = entity; + this.stack = stack; - if( this.m_upgrade != upgrade ) + if( this.upgrade != upgrade ) { - this.m_upgrade = upgrade; + this.upgrade = upgrade; this.invalidatePeripheral(); } } @@ -197,10 +197,10 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces { super.broadcastState( force ); - if( (this.hasTerminalChanged() || force) && this.m_entity instanceof ServerPlayerEntity ) + if( (this.hasTerminalChanged() || force) && this.entity instanceof ServerPlayerEntity ) { // Broadcast the state to the current entity if they're not already interacting with it. - ServerPlayerEntity player = (ServerPlayerEntity) this.m_entity; + ServerPlayerEntity player = (ServerPlayerEntity) this.entity; if( player.networkHandler != null && !this.isInteracting( player ) ) { NetworkHandler.sendToPlayer( player, this.createTerminalPacket() ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index 091d757f9..07c64678f 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -51,11 +51,11 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default public static final int INVENTORY_SIZE = 16; public static final int INVENTORY_WIDTH = 4; public static final int INVENTORY_HEIGHT = 4; - private final DefaultedList m_inventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); - private final DefaultedList m_previousInventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); - private boolean m_inventoryChanged = false; - private TurtleBrain m_brain = new TurtleBrain( this ); - private MoveState m_moveState = MoveState.NOT_MOVED; + private final DefaultedList inventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); + private final DefaultedList previousInventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); + private boolean inventoryChanged = false; + private TurtleBrain brain = new TurtleBrain( this ); + private MoveState moveState = MoveState.NOT_MOVED; public TileTurtle( BlockEntityType type, ComputerFamily family ) { @@ -105,7 +105,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default private boolean hasMoved() { - return this.m_moveState == MoveState.MOVED; + return this.moveState == MoveState.MOVED; } @Override @@ -117,7 +117,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Override public boolean isEmpty() { - for( ItemStack stack : this.m_inventory ) + for( ItemStack stack : this.inventory ) { if( !stack.isEmpty() ) { @@ -131,7 +131,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Override public ItemStack getStack( int slot ) { - return slot >= 0 && slot < INVENTORY_SIZE ? this.m_inventory.get( slot ) : ItemStack.EMPTY; + return slot >= 0 && slot < INVENTORY_SIZE ? this.inventory.get( slot ) : ItemStack.EMPTY; } @Nonnull @@ -172,9 +172,9 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Override public void setStack( int i, @Nonnull ItemStack stack ) { - if( i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual( stack, this.m_inventory.get( i ) ) ) + if( i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual( stack, this.inventory.get( i ) ) ) { - this.m_inventory.set( i, stack ); + this.inventory.set( i, stack ); this.onInventoryDefinitelyChanged(); } } @@ -188,7 +188,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default private void onInventoryDefinitelyChanged() { super.markDirty(); - this.m_inventoryChanged = true; + this.inventoryChanged = true; } @Override @@ -211,9 +211,9 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default if( !this.getWorld().isClient ) { DyeColor dye = ((DyeItem) currentItem.getItem()).getColor(); - if( this.m_brain.getDyeColour() != dye ) + if( this.brain.getDyeColour() != dye ) { - this.m_brain.setDyeColour( dye ); + this.brain.setDyeColour( dye ); if( !player.isCreative() ) { currentItem.decrement( 1 ); @@ -222,14 +222,14 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default } return ActionResult.SUCCESS; } - else if( currentItem.getItem() == Items.WATER_BUCKET && this.m_brain.getColour() != -1 ) + else if( currentItem.getItem() == Items.WATER_BUCKET && this.brain.getColour() != -1 ) { // Water to remove turtle colour if( !this.getWorld().isClient ) { - if( this.m_brain.getColour() != -1 ) + if( this.brain.getColour() != -1 ) { - this.m_brain.setColour( -1 ); + this.brain.setColour( -1 ); if( !player.isCreative() ) { player.setStackInHand( hand, new ItemStack( Items.BUCKET ) ); @@ -248,7 +248,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Override public void onNeighbourChange( @Nonnull BlockPos neighbour ) { - if( this.m_moveState == MoveState.NOT_MOVED ) + if( this.moveState == MoveState.NOT_MOVED ) { super.onNeighbourChange( neighbour ); } @@ -257,7 +257,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Override public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) { - if( this.m_moveState == MoveState.NOT_MOVED ) + if( this.moveState == MoveState.NOT_MOVED ) { super.onNeighbourTileEntityChange( neighbour ); } @@ -267,8 +267,8 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default public void tick() { super.tick(); - this.m_brain.update(); - if( !this.getWorld().isClient && this.m_inventoryChanged ) + this.brain.update(); + if( !this.getWorld().isClient && this.inventoryChanged ) { ServerComputer computer = this.getServerComputer(); if( computer != null ) @@ -276,10 +276,10 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default computer.queueEvent( "turtle_inventory" ); } - this.m_inventoryChanged = false; + this.inventoryChanged = false; for( int n = 0; n < this.size(); n++ ) { - this.m_previousInventory.set( n, + this.previousInventory.set( n, this.getStack( n ).copy() ); } } @@ -298,12 +298,12 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default ListTag nbttaglist = new ListTag(); for( int i = 0; i < INVENTORY_SIZE; i++ ) { - if( !this.m_inventory.get( i ) + if( !this.inventory.get( i ) .isEmpty() ) { CompoundTag tag = new CompoundTag(); tag.putByte( "Slot", (byte) i ); - this.m_inventory.get( i ) + this.inventory.get( i ) .toTag( tag ); nbttaglist.add( tag ); } @@ -311,7 +311,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default nbt.put( "Items", nbttaglist ); // Write brain - nbt = this.m_brain.writeToNBT( nbt ); + nbt = this.brain.writeToNBT( nbt ); return super.toTag( nbt ); } @@ -325,22 +325,22 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default // Read inventory ListTag nbttaglist = nbt.getList( "Items", NBTUtil.TAG_COMPOUND ); - this.m_inventory.clear(); - this.m_previousInventory.clear(); + this.inventory.clear(); + this.previousInventory.clear(); for( int i = 0; i < nbttaglist.size(); i++ ) { CompoundTag tag = nbttaglist.getCompound( i ); int slot = tag.getByte( "Slot" ) & 0xff; if( slot < this.size() ) { - this.m_inventory.set( slot, ItemStack.fromTag( tag ) ); - this.m_previousInventory.set( slot, this.m_inventory.get( slot ) + this.inventory.set( slot, ItemStack.fromTag( tag ) ); + this.previousInventory.set( slot, this.inventory.get( slot ) .copy() ); } } // Read state - this.m_brain.readFromNBT( nbt ); + this.brain.readFromNBT( nbt ); } @Override @@ -367,7 +367,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default ComputerCraft.turtleTermHeight ); computer.setPosition( this.getPos() ); computer.addAPI( new TurtleAPI( computer.getAPIEnvironment(), this.getAccess() ) ); - this.m_brain.setupComputer( computer ); + this.brain.setupComputer( computer ); return computer; } @@ -375,20 +375,20 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default protected void writeDescription( @Nonnull CompoundTag nbt ) { super.writeDescription( nbt ); - this.m_brain.writeDescription( nbt ); + this.brain.writeDescription( nbt ); } @Override protected void readDescription( @Nonnull CompoundTag nbt ) { super.readDescription( nbt ); - this.m_brain.readDescription( nbt ); + this.brain.readDescription( nbt ); } @Override public ComputerProxy createProxy() { - return this.m_brain.getProxy(); + return this.brain.getProxy(); } public void setDirection( Direction dir ) @@ -437,66 +437,66 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default public void notifyMoveStart() { - if( this.m_moveState == MoveState.NOT_MOVED ) + if( this.moveState == MoveState.NOT_MOVED ) { - this.m_moveState = MoveState.IN_PROGRESS; + this.moveState = MoveState.IN_PROGRESS; } } public void notifyMoveEnd() { // MoveState.MOVED is final - if( this.m_moveState == MoveState.IN_PROGRESS ) + if( this.moveState == MoveState.IN_PROGRESS ) { - this.m_moveState = MoveState.NOT_MOVED; + this.moveState = MoveState.NOT_MOVED; } } @Override public int getColour() { - return this.m_brain.getColour(); + return this.brain.getColour(); } @Override public Identifier getOverlay() { - return this.m_brain.getOverlay(); + return this.brain.getOverlay(); } @Override public ITurtleUpgrade getUpgrade( TurtleSide side ) { - return this.m_brain.getUpgrade( side ); + return this.brain.getUpgrade( side ); } @Override public ITurtleAccess getAccess() { - return this.m_brain; + return this.brain; } @Override public Vec3d getRenderOffset( float f ) { - return this.m_brain.getRenderOffset( f ); + return this.brain.getRenderOffset( f ); } @Override public float getRenderYaw( float f ) { - return this.m_brain.getVisualYaw( f ); + return this.brain.getVisualYaw( f ); } @Override public float getToolRenderAngle( TurtleSide side, float f ) { - return this.m_brain.getToolRenderAngle( side, f ); + return this.brain.getToolRenderAngle( side, f ); } void setOwningPlayer( GameProfile player ) { - this.m_brain.setOwningPlayer( player ); + this.brain.setOwningPlayer( player ); this.markDirty(); } @@ -506,13 +506,13 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default public void markDirty() { super.markDirty(); - if( !this.m_inventoryChanged ) + if( !this.inventoryChanged ) { for( int n = 0; n < this.size(); n++ ) { - if( !ItemStack.areEqual( this.getStack( n ), this.m_previousInventory.get( n ) ) ) + if( !ItemStack.areEqual( this.getStack( n ), this.previousInventory.get( n ) ) ) { - this.m_inventoryChanged = true; + this.inventoryChanged = true; break; } } @@ -525,10 +525,10 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default boolean changed = false; for( int i = 0; i < INVENTORY_SIZE; i++ ) { - if( !this.m_inventory.get( i ) + if( !this.inventory.get( i ) .isEmpty() ) { - this.m_inventory.set( i, ItemStack.EMPTY ); + this.inventory.set( i, ItemStack.EMPTY ); changed = true; } } @@ -544,21 +544,21 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default public void transferStateFrom( TileTurtle copy ) { super.transferStateFrom( copy ); - Collections.copy( this.m_inventory, copy.m_inventory ); - Collections.copy( this.m_previousInventory, copy.m_previousInventory ); - this.m_inventoryChanged = copy.m_inventoryChanged; - this.m_brain = copy.m_brain; - this.m_brain.setOwner( this ); + Collections.copy( this.inventory, copy.inventory ); + Collections.copy( this.previousInventory, copy.previousInventory ); + this.inventoryChanged = copy.inventoryChanged; + this.brain = copy.brain; + this.brain.setOwner( this ); // Mark the other turtle as having moved, and so its peripheral is dead. - copy.m_moveState = MoveState.MOVED; + copy.moveState = MoveState.MOVED; } @Nullable @Override public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) { - return new ContainerTurtle( id, inventory, this.m_brain ); + return new ContainerTurtle( id, inventory, this.brain ); } enum MoveState diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index 870fcb2a0..3cfd4ee4b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -59,51 +59,51 @@ public class TurtleBrain implements ITurtleAccess private static final String NBT_SLOT = "Slot"; private static final int ANIM_DURATION = 8; - private final Queue m_commandQueue = new ArrayDeque<>(); - private final Map m_upgrades = new EnumMap<>( TurtleSide.class ); + private final Queue commandQueue = new ArrayDeque<>(); + private final Map upgrades = new EnumMap<>( TurtleSide.class ); private final Map peripherals = new EnumMap<>( TurtleSide.class ); - private final Map m_upgradeNBTData = new EnumMap<>( TurtleSide.class ); - TurtlePlayer m_cachedPlayer; - private TileTurtle m_owner; - private final Inventory m_inventory = (InventoryDelegate) () -> this.m_owner; - private ComputerProxy m_proxy; - private GameProfile m_owningPlayer; - private int m_commandsIssued = 0; - private int m_selectedSlot = 0; - private int m_fuelLevel = 0; - private int m_colourHex = -1; - private Identifier m_overlay = null; - private TurtleAnimation m_animation = TurtleAnimation.NONE; - private int m_animationProgress = 0; - private int m_lastAnimationProgress = 0; + private final Map upgradeNBTData = new EnumMap<>( TurtleSide.class ); + TurtlePlayer cachedPlayer; + private TileTurtle owner; + private final Inventory inventory = (InventoryDelegate) () -> this.owner; + private ComputerProxy proxy; + private GameProfile owningPlayer; + private int commandsIssued = 0; + private int selectedSlot = 0; + private int fuelLevel = 0; + private int colourHex = -1; + private Identifier overlay = null; + private TurtleAnimation animation = TurtleAnimation.NONE; + private int animationProgress = 0; + private int lastAnimationProgress = 0; public TurtleBrain( TileTurtle turtle ) { - this.m_owner = turtle; + this.owner = turtle; } public TileTurtle getOwner() { - return this.m_owner; + return this.owner; } public void setOwner( TileTurtle owner ) { - this.m_owner = owner; + this.owner = owner; } public ComputerProxy getProxy() { - if( this.m_proxy == null ) + if( this.proxy == null ) { - this.m_proxy = new ComputerProxy( () -> this.m_owner ); + this.proxy = new ComputerProxy( () -> this.owner ); } - return this.m_proxy; + return this.proxy; } public ComputerFamily getFamily() { - return this.m_owner.getFamily(); + return this.owner.getFamily(); } public void setupComputer( ServerComputer computer ) @@ -168,16 +168,16 @@ public class TurtleBrain implements ITurtleAccess // The block may have been broken while the command was executing (for instance, if a block explodes // when being mined). If so, abort. - if( m_owner.isRemoved() ) return; + if( owner.isRemoved() ) return; } // Advance animation this.updateAnimation(); // Advance upgrades - if( !this.m_upgrades.isEmpty() ) + if( !this.upgrades.isEmpty() ) { - for( Map.Entry entry : this.m_upgrades.entrySet() ) + for( Map.Entry entry : this.upgrades.entrySet() ) { entry.getValue() .update( this, entry.getKey() ); @@ -189,14 +189,14 @@ public class TurtleBrain implements ITurtleAccess @Override public World getWorld() { - return this.m_owner.getWorld(); + return this.owner.getWorld(); } @Nonnull @Override public BlockPos getPosition() { - return this.m_owner.getPos(); + return this.owner.getPos(); } @Override @@ -209,9 +209,9 @@ public class TurtleBrain implements ITurtleAccess // Cache info about the old turtle (so we don't access this after we delete ourselves) World oldWorld = this.getWorld(); - TileTurtle oldOwner = this.m_owner; - BlockPos oldPos = this.m_owner.getPos(); - BlockState oldBlock = this.m_owner.getCachedState(); + TileTurtle oldOwner = this.owner; + BlockPos oldPos = this.owner.getPos(); + BlockState oldBlock = this.owner.getCachedState(); if( oldWorld == world && oldPos.equals( pos ) ) { @@ -292,7 +292,7 @@ public class TurtleBrain implements ITurtleAccess public Vec3d getVisualPosition( float f ) { Vec3d offset = this.getRenderOffset( f ); - BlockPos pos = this.m_owner.getPos(); + BlockPos pos = this.owner.getPos(); return new Vec3d( pos.getX() + 0.5 + offset.x, pos.getY() + 0.5 + offset.y, pos.getZ() + 0.5 + offset.z ); } @@ -300,7 +300,7 @@ public class TurtleBrain implements ITurtleAccess public float getVisualYaw( float f ) { float yaw = this.getDirection().asRotation(); - switch( this.m_animation ) + switch( this.animation ) { case TURN_LEFT: { @@ -328,19 +328,19 @@ public class TurtleBrain implements ITurtleAccess @Override public Direction getDirection() { - return this.m_owner.getDirection(); + return this.owner.getDirection(); } @Override public void setDirection( @Nonnull Direction dir ) { - this.m_owner.setDirection( dir ); + this.owner.setDirection( dir ); } @Override public int getSelectedSlot() { - return this.m_selectedSlot; + return this.selectedSlot; } @Override @@ -351,17 +351,17 @@ public class TurtleBrain implements ITurtleAccess throw new UnsupportedOperationException( "Cannot set the slot on the client" ); } - if( slot >= 0 && slot < this.m_owner.size() ) + if( slot >= 0 && slot < this.owner.size() ) { - this.m_selectedSlot = slot; - this.m_owner.onTileEntityChange(); + this.selectedSlot = slot; + this.owner.onTileEntityChange(); } } @Override public int getColour() { - return this.m_colourHex; + return this.colourHex; } @Override @@ -369,16 +369,16 @@ public class TurtleBrain implements ITurtleAccess { if( colour >= 0 && colour <= 0xFFFFFF ) { - if( this.m_colourHex != colour ) + if( this.colourHex != colour ) { - this.m_colourHex = colour; - this.m_owner.updateBlock(); + this.colourHex = colour; + this.owner.updateBlock(); } } - else if( this.m_colourHex != -1 ) + else if( this.colourHex != -1 ) { - this.m_colourHex = -1; - this.m_owner.updateBlock(); + this.colourHex = -1; + this.owner.updateBlock(); } } @@ -386,7 +386,7 @@ public class TurtleBrain implements ITurtleAccess @Override public GameProfile getOwningPlayer() { - return this.m_owningPlayer; + return this.owningPlayer; } @Override @@ -398,20 +398,20 @@ public class TurtleBrain implements ITurtleAccess @Override public int getFuelLevel() { - return Math.min( this.m_fuelLevel, this.getFuelLimit() ); + return Math.min( this.fuelLevel, this.getFuelLimit() ); } @Override public void setFuelLevel( int level ) { - this.m_fuelLevel = Math.min( level, this.getFuelLimit() ); - this.m_owner.onTileEntityChange(); + this.fuelLevel = Math.min( level, this.getFuelLimit() ); + this.owner.onTileEntityChange(); } @Override public int getFuelLimit() { - if( this.m_owner.getFamily() == ComputerFamily.ADVANCED ) + if( this.owner.getFamily() == ComputerFamily.ADVANCED ) { return ComputerCraft.advancedTurtleFuelLimit; } @@ -471,8 +471,8 @@ public class TurtleBrain implements ITurtleAccess private int issueCommand( ITurtleCommand command ) { - this.m_commandQueue.offer( new TurtleCommandQueueEntry( ++this.m_commandsIssued, command ) ); - return this.m_commandsIssued; + this.commandQueue.offer( new TurtleCommandQueueEntry( ++this.commandsIssued, command ) ); + return this.commandsIssued; } @Override @@ -483,37 +483,37 @@ public class TurtleBrain implements ITurtleAccess throw new UnsupportedOperationException( "Cannot play animations on the client" ); } - this.m_animation = animation; - if( this.m_animation == TurtleAnimation.SHORT_WAIT ) + this.animation = animation; + if( this.animation == TurtleAnimation.SHORT_WAIT ) { - this.m_animationProgress = ANIM_DURATION / 2; - this.m_lastAnimationProgress = ANIM_DURATION / 2; + this.animationProgress = ANIM_DURATION / 2; + this.lastAnimationProgress = ANIM_DURATION / 2; } else { - this.m_animationProgress = 0; - this.m_lastAnimationProgress = 0; + this.animationProgress = 0; + this.lastAnimationProgress = 0; } - this.m_owner.updateBlock(); + this.owner.updateBlock(); } @Override public ITurtleUpgrade getUpgrade( @Nonnull TurtleSide side ) { - return this.m_upgrades.get( side ); + return this.upgrades.get( side ); } @Override public void setUpgrade( @Nonnull TurtleSide side, ITurtleUpgrade upgrade ) { // Remove old upgrade - if( this.m_upgrades.containsKey( side ) ) + if( this.upgrades.containsKey( side ) ) { - if( this.m_upgrades.get( side ) == upgrade ) + if( this.upgrades.get( side ) == upgrade ) { return; } - this.m_upgrades.remove( side ); + this.upgrades.remove( side ); } else { @@ -523,19 +523,19 @@ public class TurtleBrain implements ITurtleAccess } } - this.m_upgradeNBTData.remove( side ); + this.upgradeNBTData.remove( side ); // Set new upgrade if( upgrade != null ) { - this.m_upgrades.put( side, upgrade ); + this.upgrades.put( side, upgrade ); } // Notify clients and create peripherals - if( this.m_owner.getWorld() != null ) + if( this.owner.getWorld() != null ) { - this.updatePeripherals( this.m_owner.createServerComputer() ); - this.m_owner.updateBlock(); + this.updatePeripherals( this.owner.createServerComputer() ); + this.owner.updateBlock(); } } @@ -549,10 +549,10 @@ public class TurtleBrain implements ITurtleAccess @Override public CompoundTag getUpgradeNBTData( TurtleSide side ) { - CompoundTag nbt = this.m_upgradeNBTData.get( side ); + CompoundTag nbt = this.upgradeNBTData.get( side ); if( nbt == null ) { - this.m_upgradeNBTData.put( side, nbt = new CompoundTag() ); + this.upgradeNBTData.put( side, nbt = new CompoundTag() ); } return nbt; } @@ -560,30 +560,30 @@ public class TurtleBrain implements ITurtleAccess @Override public void updateUpgradeNBTData( @Nonnull TurtleSide side ) { - this.m_owner.updateBlock(); + this.owner.updateBlock(); } @Nonnull @Override public Inventory getInventory() { - return this.m_inventory; + return this.inventory; } public void setOwningPlayer( GameProfile profile ) { - this.m_owningPlayer = profile; + this.owningPlayer = profile; } private void updateCommands() { - if( this.m_animation != TurtleAnimation.NONE || this.m_commandQueue.isEmpty() ) + if( this.animation != TurtleAnimation.NONE || this.commandQueue.isEmpty() ) { return; } // If we've got a computer, ensure that we're allowed to perform work. - ServerComputer computer = this.m_owner.getServerComputer(); + ServerComputer computer = this.owner.getServerComputer(); if( computer != null && !computer.getComputer() .getMainThreadMonitor() .canWork() ) @@ -592,7 +592,7 @@ public class TurtleBrain implements ITurtleAccess } // Pull a new command - TurtleCommandQueueEntry nextCommand = this.m_commandQueue.poll(); + TurtleCommandQueueEntry nextCommand = this.commandQueue.poll(); if( nextCommand == null ) { return; @@ -648,18 +648,18 @@ public class TurtleBrain implements ITurtleAccess private void updateAnimation() { - if( this.m_animation != TurtleAnimation.NONE ) + if( this.animation != TurtleAnimation.NONE ) { World world = this.getWorld(); if( ComputerCraft.turtlesCanPush ) { // Advance entity pushing - if( this.m_animation == TurtleAnimation.MOVE_FORWARD || this.m_animation == TurtleAnimation.MOVE_BACK || this.m_animation == TurtleAnimation.MOVE_UP || this.m_animation == TurtleAnimation.MOVE_DOWN ) + if( this.animation == TurtleAnimation.MOVE_FORWARD || this.animation == TurtleAnimation.MOVE_BACK || this.animation == TurtleAnimation.MOVE_UP || this.animation == TurtleAnimation.MOVE_DOWN ) { BlockPos pos = this.getPosition(); Direction moveDir; - switch( this.m_animation ) + switch( this.animation ) { case MOVE_FORWARD: default: @@ -683,7 +683,7 @@ public class TurtleBrain implements ITurtleAccess double maxY = minY + 1.0; double maxZ = minZ + 1.0; - float pushFrac = 1.0f - (float) (this.m_animationProgress + 1) / ANIM_DURATION; + float pushFrac = 1.0f - (float) (this.animationProgress + 1) / ANIM_DURATION; float push = Math.max( pushFrac + 0.0125f, 0.0f ); if( moveDir.getOffsetX() < 0 ) { @@ -729,7 +729,7 @@ public class TurtleBrain implements ITurtleAccess } // Advance valentines day easter egg - if( world.isClient && this.m_animation == TurtleAnimation.MOVE_FORWARD && this.m_animationProgress == 4 ) + if( world.isClient && this.animation == TurtleAnimation.MOVE_FORWARD && this.animationProgress == 4 ) { // Spawn love pfx if valentines day Holiday currentHoliday = HolidayUtil.getCurrentHoliday(); @@ -753,19 +753,19 @@ public class TurtleBrain implements ITurtleAccess } // Wait for anim completion - this.m_lastAnimationProgress = this.m_animationProgress; - if( ++this.m_animationProgress >= ANIM_DURATION ) + this.lastAnimationProgress = this.animationProgress; + if( ++this.animationProgress >= ANIM_DURATION ) { - this.m_animation = TurtleAnimation.NONE; - this.m_animationProgress = 0; - this.m_lastAnimationProgress = 0; + this.animation = TurtleAnimation.NONE; + this.animationProgress = 0; + this.lastAnimationProgress = 0; } } } public Vec3d getRenderOffset( float f ) { - switch( this.m_animation ) + switch( this.animation ) { case MOVE_FORWARD: case MOVE_BACK: @@ -774,7 +774,7 @@ public class TurtleBrain implements ITurtleAccess { // Get direction Direction dir; - switch( this.m_animation ) + switch( this.animation ) { case MOVE_FORWARD: default: @@ -803,8 +803,8 @@ public class TurtleBrain implements ITurtleAccess private float getAnimationFraction( float f ) { - float next = (float) this.m_animationProgress / ANIM_DURATION; - float previous = (float) this.m_lastAnimationProgress / ANIM_DURATION; + float next = (float) this.animationProgress / ANIM_DURATION; + float previous = (float) this.lastAnimationProgress / ANIM_DURATION; return previous + (next - previous) * f; } @@ -813,17 +813,17 @@ public class TurtleBrain implements ITurtleAccess this.readCommon( nbt ); // Read state - this.m_selectedSlot = nbt.getInt( NBT_SLOT ); + this.selectedSlot = nbt.getInt( NBT_SLOT ); // Read owner if( nbt.contains( "Owner", NBTUtil.TAG_COMPOUND ) ) { CompoundTag owner = nbt.getCompound( "Owner" ); - this.m_owningPlayer = new GameProfile( new UUID( owner.getLong( "UpperId" ), owner.getLong( "LowerId" ) ), owner.getString( "Name" ) ); + this.owningPlayer = new GameProfile( new UUID( owner.getLong( "UpperId" ), owner.getLong( "LowerId" ) ), owner.getString( "Name" ) ); } else { - this.m_owningPlayer = null; + this.owningPlayer = null; } } @@ -835,25 +835,25 @@ public class TurtleBrain implements ITurtleAccess private void readCommon( CompoundTag nbt ) { // Read fields - this.m_colourHex = nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : -1; - this.m_fuelLevel = nbt.contains( NBT_FUEL ) ? nbt.getInt( NBT_FUEL ) : 0; - this.m_overlay = nbt.contains( NBT_OVERLAY ) ? new Identifier( nbt.getString( NBT_OVERLAY ) ) : null; + this.colourHex = nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : -1; + this.fuelLevel = nbt.contains( NBT_FUEL ) ? nbt.getInt( NBT_FUEL ) : 0; + this.overlay = nbt.contains( NBT_OVERLAY ) ? new Identifier( nbt.getString( NBT_OVERLAY ) ) : null; // Read upgrades this.setUpgrade( TurtleSide.LEFT, nbt.contains( NBT_LEFT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_LEFT_UPGRADE ) ) : null ); this.setUpgrade( TurtleSide.RIGHT, nbt.contains( NBT_RIGHT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_RIGHT_UPGRADE ) ) : null ); // NBT - this.m_upgradeNBTData.clear(); + this.upgradeNBTData.clear(); if( nbt.contains( NBT_LEFT_UPGRADE_DATA ) ) { - this.m_upgradeNBTData.put( TurtleSide.LEFT, + this.upgradeNBTData.put( TurtleSide.LEFT, nbt.getCompound( NBT_LEFT_UPGRADE_DATA ) .copy() ); } if( nbt.contains( NBT_RIGHT_UPGRADE_DATA ) ) { - this.m_upgradeNBTData.put( TurtleSide.RIGHT, + this.upgradeNBTData.put( TurtleSide.RIGHT, nbt.getCompound( NBT_RIGHT_UPGRADE_DATA ) .copy() ); } @@ -864,19 +864,19 @@ public class TurtleBrain implements ITurtleAccess this.writeCommon( nbt ); // Write state - nbt.putInt( NBT_SLOT, this.m_selectedSlot ); + nbt.putInt( NBT_SLOT, this.selectedSlot ); // Write owner - if( this.m_owningPlayer != null ) + if( this.owningPlayer != null ) { CompoundTag owner = new CompoundTag(); nbt.put( "Owner", owner ); - owner.putLong( "UpperId", this.m_owningPlayer.getId() + owner.putLong( "UpperId", this.owningPlayer.getId() .getMostSignificantBits() ); - owner.putLong( "LowerId", this.m_owningPlayer.getId() + owner.putLong( "LowerId", this.owningPlayer.getId() .getLeastSignificantBits() ); - owner.putString( "Name", this.m_owningPlayer.getName() ); + owner.putString( "Name", this.owningPlayer.getName() ); } return nbt; @@ -884,14 +884,14 @@ public class TurtleBrain implements ITurtleAccess private void writeCommon( CompoundTag nbt ) { - nbt.putInt( NBT_FUEL, this.m_fuelLevel ); - if( this.m_colourHex != -1 ) + nbt.putInt( NBT_FUEL, this.fuelLevel ); + if( this.colourHex != -1 ) { - nbt.putInt( NBT_COLOUR, this.m_colourHex ); + nbt.putInt( NBT_COLOUR, this.colourHex ); } - if( this.m_overlay != null ) + if( this.overlay != null ) { - nbt.putString( NBT_OVERLAY, this.m_overlay.toString() ); + nbt.putString( NBT_OVERLAY, this.overlay.toString() ); } // Write upgrades @@ -907,12 +907,12 @@ public class TurtleBrain implements ITurtleAccess } // Write upgrade NBT - if( this.m_upgradeNBTData.containsKey( TurtleSide.LEFT ) ) + if( this.upgradeNBTData.containsKey( TurtleSide.LEFT ) ) { nbt.put( NBT_LEFT_UPGRADE_DATA, this.getUpgradeNBTData( TurtleSide.LEFT ).copy() ); } - if( this.m_upgradeNBTData.containsKey( TurtleSide.RIGHT ) ) + if( this.upgradeNBTData.containsKey( TurtleSide.RIGHT ) ) { nbt.put( NBT_RIGHT_UPGRADE_DATA, this.getUpgradeNBTData( TurtleSide.RIGHT ).copy() ); @@ -931,41 +931,41 @@ public class TurtleBrain implements ITurtleAccess // Animation TurtleAnimation anim = TurtleAnimation.values()[nbt.getInt( "Animation" )]; - if( anim != this.m_animation && anim != TurtleAnimation.WAIT && anim != TurtleAnimation.SHORT_WAIT && anim != TurtleAnimation.NONE ) + if( anim != this.animation && anim != TurtleAnimation.WAIT && anim != TurtleAnimation.SHORT_WAIT && anim != TurtleAnimation.NONE ) { - this.m_animation = anim; - this.m_animationProgress = 0; - this.m_lastAnimationProgress = 0; + this.animation = anim; + this.animationProgress = 0; + this.lastAnimationProgress = 0; } } public void writeDescription( CompoundTag nbt ) { this.writeCommon( nbt ); - nbt.putInt( "Animation", this.m_animation.ordinal() ); + nbt.putInt( "Animation", this.animation.ordinal() ); } public Identifier getOverlay() { - return this.m_overlay; + return this.overlay; } public void setOverlay( Identifier overlay ) { - if( !Objects.equal( this.m_overlay, overlay ) ) + if( !Objects.equal( this.overlay, overlay ) ) { - this.m_overlay = overlay; - this.m_owner.updateBlock(); + this.overlay = overlay; + this.owner.updateBlock(); } } public DyeColor getDyeColour() { - if( this.m_colourHex == -1 ) + if( this.colourHex == -1 ) { return null; } - Colour colour = Colour.fromHex( this.m_colourHex ); + Colour colour = Colour.fromHex( this.colourHex ); return colour == null ? null : DyeColor.byId( 15 - colour.ordinal() ); } @@ -976,16 +976,16 @@ public class TurtleBrain implements ITurtleAccess { newColour = Colour.values()[15 - dyeColour.getId()].getHex(); } - if( this.m_colourHex != newColour ) + if( this.colourHex != newColour ) { - this.m_colourHex = newColour; - this.m_owner.updateBlock(); + this.colourHex = newColour; + this.owner.updateBlock(); } } public float getToolRenderAngle( TurtleSide side, float f ) { - return (side == TurtleSide.LEFT && this.m_animation == TurtleAnimation.SWING_LEFT_TOOL) || (side == TurtleSide.RIGHT && this.m_animation == TurtleAnimation.SWING_RIGHT_TOOL) ? 45.0f * (float) Math.sin( + return (side == TurtleSide.LEFT && this.animation == TurtleAnimation.SWING_LEFT_TOOL) || (side == TurtleSide.RIGHT && this.animation == TurtleAnimation.SWING_RIGHT_TOOL) ? 45.0f * (float) Math.sin( this.getAnimationFraction( f ) * Math.PI ) : 0.0f; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java index 69fb115d3..b362f5d8b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java @@ -22,11 +22,11 @@ import java.util.List; public class TurtleCompareCommand implements ITurtleCommand { - private final InteractDirection m_direction; + private final InteractDirection direction; public TurtleCompareCommand( InteractDirection direction ) { - this.m_direction = direction; + this.direction = direction; } @Nonnull @@ -34,7 +34,7 @@ public class TurtleCompareCommand implements ITurtleCommand public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Get world direction from direction - Direction direction = this.m_direction.toWorldDir( turtle ); + Direction direction = this.direction.toWorldDir( turtle ); // Get currently selected stack ItemStack selectedStack = turtle.getInventory() diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java index c34cd8856..10297aea9 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java @@ -16,11 +16,11 @@ import javax.annotation.Nonnull; public class TurtleCompareToCommand implements ITurtleCommand { - private final int m_slot; + private final int slot; public TurtleCompareToCommand( int slot ) { - this.m_slot = slot; + this.slot = slot; } @Nonnull @@ -30,7 +30,7 @@ public class TurtleCompareToCommand implements ITurtleCommand ItemStack selectedStack = turtle.getInventory() .getStack( turtle.getSelectedSlot() ); ItemStack stack = turtle.getInventory() - .getStack( this.m_slot ); + .getStack( this.slot ); if( InventoryUtil.areItemsStackable( selectedStack, stack ) ) { return TurtleCommandResult.success(); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java index 269bb9388..cbc97f931 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java @@ -18,11 +18,11 @@ import javax.annotation.Nonnull; public class TurtleDetectCommand implements ITurtleCommand { - private final InteractDirection m_direction; + private final InteractDirection direction; public TurtleDetectCommand( InteractDirection direction ) { - this.m_direction = direction; + this.direction = direction; } @Nonnull @@ -30,7 +30,7 @@ public class TurtleDetectCommand implements ITurtleCommand public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Get world direction from direction - Direction direction = this.m_direction.toWorldDir( turtle ); + Direction direction = this.direction.toWorldDir( turtle ); // Check if thing in front is air or not World world = turtle.getWorld(); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java index 611d63f1c..94b4a52bf 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java @@ -25,13 +25,13 @@ import javax.annotation.Nonnull; public class TurtleDropCommand implements ITurtleCommand { - private final InteractDirection m_direction; - private final int m_quantity; + private final InteractDirection direction; + private final int quantity; public TurtleDropCommand( InteractDirection direction, int quantity ) { - this.m_direction = direction; - this.m_quantity = quantity; + this.direction = direction; + this.quantity = quantity; } @Nonnull @@ -39,17 +39,17 @@ public class TurtleDropCommand implements ITurtleCommand public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Dropping nothing is easy - if( this.m_quantity == 0 ) + if( this.quantity == 0 ) { turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); } // Get world direction from direction - Direction direction = this.m_direction.toWorldDir( turtle ); + Direction direction = this.direction.toWorldDir( turtle ); // Get things to drop - ItemStack stack = InventoryUtil.takeItems( this.m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + ItemStack stack = InventoryUtil.takeItems( this.quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); if( stack.isEmpty() ) { return TurtleCommandResult.failure( "No items to drop" ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java index b8455962a..58fb06c8b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java @@ -22,11 +22,11 @@ import javax.annotation.Nonnull; public class TurtleEquipCommand implements ITurtleCommand { - private final TurtleSide m_side; + private final TurtleSide side; public TurtleEquipCommand( TurtleSide side ) { - this.m_side = side; + this.side = side; } @Nonnull @@ -55,7 +55,7 @@ public class TurtleEquipCommand implements ITurtleCommand // Determine the upgrade to replace ItemStack oldUpgradeStack; - ITurtleUpgrade oldUpgrade = turtle.getUpgrade( this.m_side ); + ITurtleUpgrade oldUpgrade = turtle.getUpgrade( this.side ); if( oldUpgrade != null ) { ItemStack craftingItem = oldUpgrade.getCraftingItem(); @@ -89,7 +89,7 @@ public class TurtleEquipCommand implements ITurtleCommand WorldUtil.dropItemStack( remainder, turtle.getWorld(), position, turtle.getDirection() ); } } - turtle.setUpgrade( this.m_side, newUpgrade ); + turtle.setUpgrade( this.side, newUpgrade ); // Animate if( newUpgrade != null || oldUpgrade != null ) diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java index a57bd841a..14bd79b2e 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java @@ -30,11 +30,11 @@ import java.util.List; public class TurtleMoveCommand implements ITurtleCommand { private static final Box EMPTY_BOX = new Box( 0, 0, 0, 0, 0, 0 ); - private final MoveDirection m_direction; + private final MoveDirection direction; public TurtleMoveCommand( MoveDirection direction ) { - this.m_direction = direction; + this.direction = direction; } @Nonnull @@ -42,7 +42,7 @@ public class TurtleMoveCommand implements ITurtleCommand public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Get world direction from direction - Direction direction = this.m_direction.toWorldDir( turtle ); + Direction direction = this.direction.toWorldDir( turtle ); // Check if we can move World oldWorld = turtle.getWorld(); @@ -70,7 +70,7 @@ public class TurtleMoveCommand implements ITurtleCommand if( !oldWorld.intersectsEntities( null, collision ) ) { - if( !ComputerCraft.turtlesCanPush || this.m_direction == MoveDirection.UP || this.m_direction == MoveDirection.DOWN ) + if( !ComputerCraft.turtlesCanPush || this.direction == MoveDirection.UP || this.direction == MoveDirection.DOWN ) { return TurtleCommandResult.failure( "Movement obstructed" ); } @@ -110,7 +110,7 @@ public class TurtleMoveCommand implements ITurtleCommand turtle.consumeFuel( 1 ); // Animate - switch( this.m_direction ) + switch( this.direction ) { case FORWARD: default: diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java index 9817d650e..93a406a86 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -40,13 +40,13 @@ import java.util.List; public class TurtlePlaceCommand implements ITurtleCommand { - private final InteractDirection m_direction; - private final Object[] m_extraArguments; + private final InteractDirection direction; + private final Object[] extraArguments; public TurtlePlaceCommand( InteractDirection direction, Object[] arguments ) { - this.m_direction = direction; - this.m_extraArguments = arguments; + this.direction = direction; + this.extraArguments = arguments; } public static ItemStack deploy( @Nonnull ItemStack stack, ITurtleAccess turtle, Direction direction, Object[] extraArguments, String[] outErrorMessage ) @@ -72,7 +72,7 @@ public class TurtlePlaceCommand implements ITurtleCommand } // Remember old block - Direction direction = this.m_direction.toWorldDir( turtle ); + Direction direction = this.direction.toWorldDir( turtle ); BlockPos coordinates = turtle.getPosition() .offset( direction ); @@ -89,7 +89,7 @@ public class TurtlePlaceCommand implements ITurtleCommand // Do the deploying String[] errorMessage = new String[1]; - ItemStack remainder = deploy( stack, turtle, turtlePlayer, direction, this.m_extraArguments, errorMessage ); + ItemStack remainder = deploy( stack, turtle, turtlePlayer, direction, this.extraArguments, errorMessage ); if( remainder != stack ) { // Put the remaining items back diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java index 5ec609d09..fff1e67bd 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java @@ -96,10 +96,10 @@ public final class TurtlePlayer extends FakePlayer if( !(access instanceof TurtleBrain) ) return create( access ); TurtleBrain brain = (TurtleBrain) access; - TurtlePlayer player = brain.m_cachedPlayer; + TurtlePlayer player = brain.cachedPlayer; if( player == null || player.getGameProfile() != getProfile( access.getOwningPlayer() ) || player.getEntityWorld() != access.getWorld() ) { - player = brain.m_cachedPlayer = create( brain ); + player = brain.cachedPlayer = create( brain ); } else { diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java index bae644c73..5a106dca4 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java @@ -28,13 +28,13 @@ import java.util.List; public class TurtleSuckCommand implements ITurtleCommand { - private final InteractDirection m_direction; - private final int m_quantity; + private final InteractDirection direction; + private final int quantity; public TurtleSuckCommand( InteractDirection direction, int quantity ) { - this.m_direction = direction; - this.m_quantity = quantity; + this.direction = direction; + this.quantity = quantity; } @Nonnull @@ -42,14 +42,14 @@ public class TurtleSuckCommand implements ITurtleCommand public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Sucking nothing is easy - if( this.m_quantity == 0 ) + if( this.quantity == 0 ) { turtle.playAnimation( TurtleAnimation.WAIT ); return TurtleCommandResult.success(); } // Get world direction from direction - Direction direction = this.m_direction.toWorldDir( turtle ); + Direction direction = this.direction.toWorldDir( turtle ); // Get inventory for thing in front World world = turtle.getWorld(); @@ -70,7 +70,7 @@ public class TurtleSuckCommand implements ITurtleCommand if( inventory != null ) { // Take from inventory of thing in front - ItemStack stack = InventoryUtil.takeItems( this.m_quantity, ItemStorage.wrap( inventory ) ); + ItemStack stack = InventoryUtil.takeItems( this.quantity, ItemStorage.wrap( inventory ) ); if( stack.isEmpty() ) { return TurtleCommandResult.failure( "No items to take" ); @@ -118,9 +118,9 @@ public class TurtleSuckCommand implements ITurtleCommand ItemStack storeStack; ItemStack leaveStack; - if( stack.getCount() > this.m_quantity ) + if( stack.getCount() > this.quantity ) { - storeStack = stack.split( this.m_quantity ); + storeStack = stack.split( this.quantity ); leaveStack = stack; } else diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java index adc971f09..930969754 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java @@ -17,13 +17,13 @@ import javax.annotation.Nonnull; public class TurtleTransferToCommand implements ITurtleCommand { - private final int m_slot; - private final int m_quantity; + private final int slot; + private final int quantity; public TurtleTransferToCommand( int slot, int limit ) { - this.m_slot = slot; - this.m_quantity = limit; + this.slot = slot; + this.quantity = limit; } @Nonnull @@ -31,7 +31,7 @@ public class TurtleTransferToCommand implements ITurtleCommand public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Take stack - ItemStack stack = InventoryUtil.takeItems( this.m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + ItemStack stack = InventoryUtil.takeItems( this.quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); if( stack.isEmpty() ) { turtle.playAnimation( TurtleAnimation.WAIT ); @@ -39,7 +39,7 @@ public class TurtleTransferToCommand implements ITurtleCommand } // Store stack - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), this.m_slot, 1, this.m_slot ); + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), this.slot, 1, this.slot ); if( !remainder.isEmpty() ) { // Put the remainder back diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java index 312f002cf..5f3f9ee5e 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java @@ -18,11 +18,11 @@ import javax.annotation.Nonnull; public class TurtleTurnCommand implements ITurtleCommand { - private final TurnDirection m_direction; + private final TurnDirection direction; public TurtleTurnCommand( TurnDirection direction ) { - this.m_direction = direction; + this.direction = direction; } @Nonnull @@ -35,7 +35,7 @@ public class TurtleTurnCommand implements ITurtleCommand return TurtleCommandResult.failure( event.getFailureMessage() ); } - switch( this.m_direction ) + switch( this.direction ) { case LEFT: { diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java index 0ebfc06a3..d7ebb5576 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java @@ -23,10 +23,10 @@ import javax.annotation.Nonnull; public class TurtleCraftingTable extends AbstractTurtleUpgrade { @Environment( EnvType.CLIENT ) - private ModelIdentifier m_leftModel; + private ModelIdentifier leftModel; @Environment( EnvType.CLIENT ) - private ModelIdentifier m_rightModel; + private ModelIdentifier rightModel; public TurtleCraftingTable( Identifier id ) { @@ -45,16 +45,16 @@ public class TurtleCraftingTable extends AbstractTurtleUpgrade public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) { this.loadModelLocations(); - return TransformedModel.of( side == TurtleSide.LEFT ? this.m_leftModel : this.m_rightModel ); + return TransformedModel.of( side == TurtleSide.LEFT ? this.leftModel : this.rightModel ); } @Environment( EnvType.CLIENT ) private void loadModelLocations() { - if( this.m_leftModel == null ) + if( this.leftModel == null ) { - this.m_leftModel = new ModelIdentifier( "computercraft:turtle_crafting_table_left", "inventory" ); - this.m_rightModel = new ModelIdentifier( "computercraft:turtle_crafting_table_right", "inventory" ); + this.leftModel = new ModelIdentifier( "computercraft:turtle_crafting_table_left", "inventory" ); + this.rightModel = new ModelIdentifier( "computercraft:turtle_crafting_table_right", "inventory" ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java index 3aa249829..f6e19fde5 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java @@ -26,9 +26,9 @@ import java.util.List; public class TurtleInventoryCrafting extends CraftingInventory { - private ITurtleAccess m_turtle; - private int m_xStart; - private int m_yStart; + private final ITurtleAccess turtle; + private int xStart; + private int yStart; @SuppressWarnings( "ConstantConditions" ) public TurtleInventoryCrafting( ITurtleAccess turtle ) @@ -36,25 +36,25 @@ public class TurtleInventoryCrafting extends CraftingInventory // Passing null in here is evil, but we don't have a container present. We override most methods in order to // avoid throwing any NPEs. super( null, 0, 0 ); - this.m_turtle = turtle; - this.m_xStart = 0; - this.m_yStart = 0; + this.turtle = turtle; + this.xStart = 0; + this.yStart = 0; } @Nullable private Recipe tryCrafting( int xStart, int yStart ) { - this.m_xStart = xStart; - this.m_yStart = yStart; + this.xStart = xStart; + this.yStart = yStart; // Check the non-relevant parts of the inventory are empty for( int x = 0; x < TileTurtle.INVENTORY_WIDTH; x++ ) { for( int y = 0; y < TileTurtle.INVENTORY_HEIGHT; y++ ) { - if( x < this.m_xStart || x >= this.m_xStart + 3 || y < this.m_yStart || y >= this.m_yStart + 3 ) + if( x < this.xStart || x >= this.xStart + 3 || y < this.yStart || y >= this.yStart + 3 ) { - if( !this.m_turtle.getInventory() + if( !this.turtle.getInventory() .getStack( x + y * TileTurtle.INVENTORY_WIDTH ) .isEmpty() ) { @@ -65,9 +65,9 @@ public class TurtleInventoryCrafting extends CraftingInventory } // Check the actual crafting - return this.m_turtle.getWorld() + return this.turtle.getWorld() .getRecipeManager() - .getFirstMatch( RecipeType.CRAFTING, this, this.m_turtle.getWorld() ) + .getFirstMatch( RecipeType.CRAFTING, this, this.turtle.getWorld() ) .orElse( null ); } @@ -104,7 +104,7 @@ public class TurtleInventoryCrafting extends CraftingInventory return Collections.emptyList(); } - TurtlePlayer player = TurtlePlayer.get( this.m_turtle ); + TurtlePlayer player = TurtlePlayer.get( this.turtle ); ArrayList results = new ArrayList<>(); for( int i = 0; i < maxCount && recipe.matches( this, world ); i++ ) @@ -159,7 +159,7 @@ public class TurtleInventoryCrafting extends CraftingInventory @Override public int getMaxCountPerStack() { - return this.m_turtle.getInventory() + return this.turtle.getInventory() .getMaxCountPerStack(); } @@ -173,7 +173,7 @@ public class TurtleInventoryCrafting extends CraftingInventory public boolean isValid( int i, @Nonnull ItemStack stack ) { i = this.modifyIndex( i ); - return this.m_turtle.getInventory() + return this.turtle.getInventory() .isValid( i, stack ); } @@ -185,8 +185,8 @@ public class TurtleInventoryCrafting extends CraftingInventory private int modifyIndex( int index ) { - int x = this.m_xStart + index % this.getWidth(); - int y = this.m_yStart + index / this.getHeight(); + int x = this.xStart + index % this.getWidth(); + int y = this.yStart + index / this.getHeight(); return x >= 0 && x < TileTurtle.INVENTORY_WIDTH && y >= 0 && y < TileTurtle.INVENTORY_HEIGHT ? x + y * TileTurtle.INVENTORY_WIDTH : -1; } @@ -203,7 +203,7 @@ public class TurtleInventoryCrafting extends CraftingInventory public ItemStack getStack( int i ) { i = this.modifyIndex( i ); - return this.m_turtle.getInventory() + return this.turtle.getInventory() .getStack( i ); } @@ -212,7 +212,7 @@ public class TurtleInventoryCrafting extends CraftingInventory public ItemStack removeStack( int i ) { i = this.modifyIndex( i ); - return this.m_turtle.getInventory() + return this.turtle.getInventory() .removeStack( i ); } @@ -221,7 +221,7 @@ public class TurtleInventoryCrafting extends CraftingInventory public ItemStack removeStack( int i, int size ) { i = this.modifyIndex( i ); - return this.m_turtle.getInventory() + return this.turtle.getInventory() .removeStack( i, size ); } @@ -229,7 +229,7 @@ public class TurtleInventoryCrafting extends CraftingInventory public void setStack( int i, @Nonnull ItemStack stack ) { i = this.modifyIndex( i ); - this.m_turtle.getInventory() + this.turtle.getInventory() .setStack( i, stack ); } @@ -237,7 +237,7 @@ public class TurtleInventoryCrafting extends CraftingInventory @Override public void markDirty() { - this.m_turtle.getInventory() + this.turtle.getInventory() .markDirty(); } @@ -254,7 +254,7 @@ public class TurtleInventoryCrafting extends CraftingInventory for( int i = 0; i < this.size(); i++ ) { int j = this.modifyIndex( i ); - this.m_turtle.getInventory() + this.turtle.getInventory() .setStack( j, ItemStack.EMPTY ); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java index e3951e563..ed94e0153 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java @@ -28,13 +28,13 @@ public class TurtleModem extends AbstractTurtleUpgrade { private final boolean advanced; @Environment( EnvType.CLIENT ) - private ModelIdentifier m_leftOffModel; + private ModelIdentifier leftOffModel; @Environment( EnvType.CLIENT ) - private ModelIdentifier m_rightOffModel; + private ModelIdentifier rightOffModel; @Environment( EnvType.CLIENT ) - private ModelIdentifier m_leftOnModel; + private ModelIdentifier leftOnModel; @Environment( EnvType.CLIENT ) - private ModelIdentifier m_rightOnModel; + private ModelIdentifier rightOnModel; public TurtleModem( boolean advanced, Identifier id ) { @@ -71,27 +71,27 @@ public class TurtleModem extends AbstractTurtleUpgrade active = turtleNBT.contains( "active" ) && turtleNBT.getBoolean( "active" ); } - return side == TurtleSide.LEFT ? TransformedModel.of( active ? this.m_leftOnModel : this.m_leftOffModel ) : TransformedModel.of( active ? this.m_rightOnModel : this.m_rightOffModel ); + return side == TurtleSide.LEFT ? TransformedModel.of( active ? this.leftOnModel : this.leftOffModel ) : TransformedModel.of( active ? this.rightOnModel : this.rightOffModel ); } @Environment( EnvType.CLIENT ) private void loadModelLocations() { - if( this.m_leftOffModel == null ) + if( this.leftOffModel == null ) { if( this.advanced ) { - this.m_leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_left", "inventory" ); - this.m_rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_right", "inventory" ); - this.m_leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_left", "inventory" ); - this.m_rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_right", "inventory" ); + this.leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_left", "inventory" ); + this.rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_right", "inventory" ); + this.leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_left", "inventory" ); + this.rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_right", "inventory" ); } else { - this.m_leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_left", "inventory" ); - this.m_rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_right", "inventory" ); - this.m_leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_left", "inventory" ); - this.m_rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_right", "inventory" ); + this.leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_left", "inventory" ); + this.rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_right", "inventory" ); + this.leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_left", "inventory" ); + this.rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_right", "inventory" ); } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java index 187080a90..0980e0928 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java @@ -26,9 +26,9 @@ import javax.annotation.Nonnull; public class TurtleSpeaker extends AbstractTurtleUpgrade { @Environment( EnvType.CLIENT ) - private ModelIdentifier m_leftModel; + private ModelIdentifier leftModel; @Environment( EnvType.CLIENT ) - private ModelIdentifier m_rightModel; + private ModelIdentifier rightModel; public TurtleSpeaker( Identifier id ) { @@ -47,16 +47,16 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) { this.loadModelLocations(); - return TransformedModel.of( side == TurtleSide.LEFT ? this.m_leftModel : this.m_rightModel ); + return TransformedModel.of( side == TurtleSide.LEFT ? this.leftModel : this.rightModel ); } @Environment( EnvType.CLIENT ) private void loadModelLocations() { - if( this.m_leftModel == null ) + if( this.leftModel == null ) { - this.m_leftModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_left", "inventory" ); - this.m_rightModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_right", "inventory" ); + this.leftModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_left", "inventory" ); + this.rightModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_right", "inventory" ); } } diff --git a/src/main/java/dan200/computercraft/shared/util/Config.java b/src/main/java/dan200/computercraft/shared/util/Config.java index fdf35bd77..b9fc34156 100644 --- a/src/main/java/dan200/computercraft/shared/util/Config.java +++ b/src/main/java/dan200/computercraft/shared/util/Config.java @@ -5,7 +5,10 @@ */ package dan200.computercraft.shared.util; -import com.electronwill.nightconfig.core.*; +import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.ConfigSpec; +import com.electronwill.nightconfig.core.EnumGetMethod; +import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.electronwill.nightconfig.core.file.FileNotFoundAction; import com.google.common.base.CaseFormat; @@ -27,7 +30,8 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -public class Config { +public class Config +{ private static final int MODEM_MAX_RANGE = 100000; public static final String TRANSLATION_PREFIX = "gui.computercraft.config."; @@ -38,327 +42,346 @@ public class Config { public static CommentedConfig serverConfig; public static CommentedConfig clientConfig; - private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath("serverconfig"); + private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath( "serverconfig" ); private static final String serverFileName = "computercraft-server.toml"; - private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve("computercraft-client.toml"); + private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve( "computercraft-client.toml" ); - private Config() { + private Config() + { } - static { - System.setProperty("nightconfig.preserveInsertionOrder", "true"); + static + { + System.setProperty( "nightconfig.preserveInsertionOrder", "true" ); serverSpec = new CommentedConfigSpec(); { // General computers - serverSpec.comment("computer_space_limit", - "The disk space limit for computers and turtles, in bytes"); - serverSpec.define("computer_space_limit", ComputerCraft.computerSpaceLimit); + serverSpec.comment( "computer_space_limit", + "The disk space limit for computers and turtles, in bytes" ); + serverSpec.define( "computer_space_limit", ComputerCraft.computerSpaceLimit ); - serverSpec.comment("floppy_space_limit", - "The disk space limit for floppy disks, in bytes"); - serverSpec.define("floppy_space_limit", ComputerCraft.floppySpaceLimit); + serverSpec.comment( "floppy_space_limit", + "The disk space limit for floppy disks, in bytes" ); + serverSpec.define( "floppy_space_limit", ComputerCraft.floppySpaceLimit ); - serverSpec.comment("maximum_open_files", - "Set how many files a computer can have open at the same time. Set to 0 for unlimited."); - serverSpec.defineInRange("maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE); + serverSpec.comment( "maximum_open_files", + "Set how many files a computer can have open at the same time. Set to 0 for unlimited." ); + serverSpec.defineInRange( "maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE ); - serverSpec.comment("disable_lua51_features", - "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + - "Useful for ensuring forward compatibility of your programs now."); - serverSpec.define("disable_lua51_features", ComputerCraft.disableLua51Features); + serverSpec.comment( "disable_lua51_features", + "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + + "Useful for ensuring forward compatibility of your programs now." ); + serverSpec.define( "disable_lua51_features", ComputerCraft.disableLua51Features ); - serverSpec.comment("default_computer_settings", - "A comma separated list of default system settings to set on new computers. Example: " + + serverSpec.comment( "default_computer_settings", + "A comma separated list of default system settings to set on new computers. Example: " + "\"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all " + - "autocompletion"); - serverSpec.define("default_computer_settings", ComputerCraft.defaultComputerSettings); + "autocompletion" ); + serverSpec.define( "default_computer_settings", ComputerCraft.defaultComputerSettings ); - serverSpec.comment("debug_enabled", - "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players."); - serverSpec.define("debug_enabled", ComputerCraft.debugEnable); + serverSpec.comment( "debug_enabled", + "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players." ); + serverSpec.define( "debug_enabled", ComputerCraft.debugEnable ); - serverSpec.comment("log_computer_errors", - "Log exceptions thrown by peripherals and other Lua objects.\n" + - "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods."); - serverSpec.define("log_computer_errors", ComputerCraft.logComputerErrors); + serverSpec.comment( "log_computer_errors", + "Log exceptions thrown by peripherals and other Lua objects.\n" + + "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods." ); + serverSpec.define( "log_computer_errors", ComputerCraft.logComputerErrors ); - serverSpec.comment("command_require_creative", - "Require players to be in creative mode and be opped in order to interact with command computers." + - "This is the default behaviour for vanilla's Command blocks."); - serverSpec.define("command_require_creative", ComputerCraft.commandRequireCreative); + serverSpec.comment( "command_require_creative", + "Require players to be in creative mode and be opped in order to interact with command computers." + + "This is the default behaviour for vanilla's Command blocks." ); + serverSpec.define( "command_require_creative", ComputerCraft.commandRequireCreative ); } { // Execution - serverSpec.comment("execution", - "Controls execution behaviour of computers. This is largely intended for fine-tuning " + - "servers, and generally shouldn't need to be touched"); + serverSpec.comment( "execution", + "Controls execution behaviour of computers. This is largely intended for fine-tuning " + + "servers, and generally shouldn't need to be touched" ); - serverSpec.comment("execution.computer_threads", - "Set the number of threads computers can run on. A higher number means more computers can run " + + serverSpec.comment( "execution.computer_threads", + "Set the number of threads computers can run on. A higher number means more computers can run " + "at once, but may induce lag.\n" + - "Please note that some mods may not work with a thread count higher than 1. Use with caution."); - serverSpec.defineInRange("execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE); + "Please note that some mods may not work with a thread count higher than 1. Use with caution." ); + serverSpec.defineInRange( "execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE ); - serverSpec.comment("execution.max_main_global_time", - "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + + serverSpec.comment( "execution.max_main_global_time", + "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time."); - serverSpec.defineInRange("execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE); + "- this aims to be the upper bound of the average time." ); + serverSpec.defineInRange( "execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE ); - serverSpec.comment("execution.max_main_computer_time", - "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + + serverSpec.comment( "execution.max_main_computer_time", + "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time."); - serverSpec.defineInRange("execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE); + "- this aims to be the upper bound of the average time." ); + serverSpec.defineInRange( "execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE ); } { // HTTP - serverSpec.comment("http", "Controls the HTTP API"); + serverSpec.comment( "http", "Controls the HTTP API" ); - serverSpec.comment("http.enabled", - "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)."); - serverSpec.define("http.enabled", ComputerCraft.httpEnabled); + serverSpec.comment( "http.enabled", + "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)." ); + serverSpec.define( "http.enabled", ComputerCraft.httpEnabled ); - serverSpec.comment("http.websocket_enabled", - "Enable use of http websockets. This requires the \"http_enable\" option to also be true."); - serverSpec.define("http.websocket_enabled", ComputerCraft.httpWebsocketEnabled); + serverSpec.comment( "http.websocket_enabled", + "Enable use of http websockets. This requires the \"http_enable\" option to also be true." ); + serverSpec.define( "http.websocket_enabled", ComputerCraft.httpWebsocketEnabled ); - serverSpec.comment("http.rules", - "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + + serverSpec.comment( "http.rules", + "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + "Each rule is an item with a 'host' to match against, and a series of properties. " + "The host may be a domain name (\"pastebin.com\"),\n" + - "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked."); - serverSpec.defineList("http.rules", Arrays.asList( - AddressRuleConfig.makeRule("$private", Action.DENY), - AddressRuleConfig.makeRule("*", Action.ALLOW) - ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule((UnmodifiableConfig) x)); + "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked." ); + serverSpec.defineList( "http.rules", Arrays.asList( + AddressRuleConfig.makeRule( "$private", Action.DENY ), + AddressRuleConfig.makeRule( "*", Action.ALLOW ) + ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule( (UnmodifiableConfig) x ) ); - serverSpec.comment("http.max_requests", - "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited."); - serverSpec.defineInRange("http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE); + serverSpec.comment( "http.max_requests", + "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited." ); + serverSpec.defineInRange( "http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE ); - serverSpec.comment("http.max_websockets", - "The number of websockets a computer can have open at one time. Set to 0 for unlimited."); - serverSpec.defineInRange("http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE); + serverSpec.comment( "http.max_websockets", + "The number of websockets a computer can have open at one time. Set to 0 for unlimited." ); + serverSpec.defineInRange( "http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE ); } { // Peripherals - serverSpec.comment("peripheral", "Various options relating to peripherals."); + serverSpec.comment( "peripheral", "Various options relating to peripherals." ); - serverSpec.comment("peripheral.command_block_enabled", - "Enable Command Block peripheral support"); - serverSpec.define("peripheral.command_block_enabled", ComputerCraft.enableCommandBlock); + serverSpec.comment( "peripheral.command_block_enabled", + "Enable Command Block peripheral support" ); + serverSpec.define( "peripheral.command_block_enabled", ComputerCraft.enableCommandBlock ); - serverSpec.comment("peripheral.modem_range", - "The range of Wireless Modems at low altitude in clear weather, in meters"); - serverSpec.defineInRange("peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_range", + "The range of Wireless Modems at low altitude in clear weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.modem_high_altitude_range", - "The range of Wireless Modems at maximum altitude in clear weather, in meters"); - serverSpec.defineInRange("peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_high_altitude_range", + "The range of Wireless Modems at maximum altitude in clear weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.modem_range_during_storm", - "The range of Wireless Modems at low altitude in stormy weather, in meters"); - serverSpec.defineInRange("peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_range_during_storm", + "The range of Wireless Modems at low altitude in stormy weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.modem_high_altitude_range_during_storm", - "The range of Wireless Modems at maximum altitude in stormy weather, in meters"); - serverSpec.defineInRange("peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE); + serverSpec.comment( "peripheral.modem_high_altitude_range_during_storm", + "The range of Wireless Modems at maximum altitude in stormy weather, in meters" ); + serverSpec.defineInRange( "peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE ); - serverSpec.comment("peripheral.max_notes_per_tick", - "Maximum amount of notes a speaker can play at once"); - serverSpec.defineInRange("peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE); + serverSpec.comment( "peripheral.max_notes_per_tick", + "Maximum amount of notes a speaker can play at once" ); + serverSpec.defineInRange( "peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE ); - serverSpec.comment("peripheral.monitor_bandwidth", - "The limit to how much monitor data can be sent *per tick*. Note:\n" + + serverSpec.comment( "peripheral.monitor_bandwidth", + "The limit to how much monitor data can be sent *per tick*. Note:\n" + " - Bandwidth is measured before compression, so the data sent to the client is smaller.\n" + " - This ignores the number of players a packet is sent to. Updating a monitor for one player consumes " + "the same bandwidth limit as sending to 20.\n" + " - A full sized monitor sends ~25kb of data. So the default (1MB) allows for ~40 monitors to be updated " + "in a single tick. \n" + - "Set to 0 to disable."); - serverSpec.defineInRange("peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE); + "Set to 0 to disable." ); + serverSpec.defineInRange( "peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE ); } { // Turtles - serverSpec.comment("turtle", "Various options relating to turtles."); + serverSpec.comment( "turtle", "Various options relating to turtles." ); - serverSpec.comment("turtle.need_fuel", - "Set whether Turtles require fuel to move"); - serverSpec.define("turtle.need_fuel", ComputerCraft.turtlesNeedFuel); + serverSpec.comment( "turtle.need_fuel", + "Set whether Turtles require fuel to move" ); + serverSpec.define( "turtle.need_fuel", ComputerCraft.turtlesNeedFuel ); - serverSpec.comment("turtle.normal_fuel_limit", "The fuel limit for Turtles"); - serverSpec.defineInRange("turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE); + serverSpec.comment( "turtle.normal_fuel_limit", "The fuel limit for Turtles" ); + serverSpec.defineInRange( "turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE ); - serverSpec.comment("turtle.advanced_fuel_limit", - "The fuel limit for Advanced Turtles"); - serverSpec.defineInRange("turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE); + serverSpec.comment( "turtle.advanced_fuel_limit", + "The fuel limit for Advanced Turtles" ); + serverSpec.defineInRange( "turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE ); - serverSpec.comment("turtle.obey_block_protection", - "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)"); - serverSpec.define("turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection); + serverSpec.comment( "turtle.obey_block_protection", + "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)" ); + serverSpec.define( "turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection ); - serverSpec.comment("turtle.can_push", - "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so"); - serverSpec.define("turtle.can_push", ComputerCraft.turtlesCanPush); + serverSpec.comment( "turtle.can_push", + "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so" ); + serverSpec.define( "turtle.can_push", ComputerCraft.turtlesCanPush ); - serverSpec.comment("turtle.disabled_actions", - "A list of turtle actions which are disabled."); - serverSpec.defineList("turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction((String) x) != null); + serverSpec.comment( "turtle.disabled_actions", + "A list of turtle actions which are disabled." ); + serverSpec.defineList( "turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction( (String) x ) != null ); } { - serverSpec.comment("term_sizes", "Configure the size of various computer's terminals.\n" + - "Larger terminals require more bandwidth, so use with care."); + serverSpec.comment( "term_sizes", "Configure the size of various computer's terminals.\n" + + "Larger terminals require more bandwidth, so use with care." ); - serverSpec.comment("term_sizes.computer", "Terminal size of computers"); - serverSpec.defineInRange("term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255); - serverSpec.defineInRange("term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255); + serverSpec.comment( "term_sizes.computer", "Terminal size of computers" ); + serverSpec.defineInRange( "term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255 ); + serverSpec.defineInRange( "term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255 ); - serverSpec.comment("term_sizes.pocket_computer", "Terminal size of pocket computers"); - serverSpec.defineInRange("term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255); - serverSpec.defineInRange("term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255); + serverSpec.comment( "term_sizes.pocket_computer", "Terminal size of pocket computers" ); + serverSpec.defineInRange( "term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255 ); + serverSpec.defineInRange( "term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255 ); - serverSpec.comment("term_sizes.monitor", "Maximum size of monitors (in blocks)"); - serverSpec.defineInRange("term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32); - serverSpec.defineInRange("term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32); + serverSpec.comment( "term_sizes.monitor", "Maximum size of monitors (in blocks)" ); + serverSpec.defineInRange( "term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32 ); + serverSpec.defineInRange( "term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32 ); } clientSpec = new CommentedConfigSpec(); - clientSpec.comment("monitor_renderer", - "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + - "monitors have performance issues, you may wish to experiment with alternative renderers."); - clientSpec.defineRestrictedEnum("monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf(MonitorRenderer.class), EnumGetMethod.NAME_IGNORECASE); + clientSpec.comment( "monitor_renderer", + "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + + "monitors have performance issues, you may wish to experiment with alternative renderers." ); + clientSpec.defineRestrictedEnum( "monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf( MonitorRenderer.class ), EnumGetMethod.NAME_IGNORECASE ); - clientSpec.comment("monitor_distance", - "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + + clientSpec.comment( "monitor_distance", + "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + "but may be extended if you wish to build larger monitors." ); - clientSpec.defineInRange("monitor_distance", 64, 16, 1024); + clientSpec.defineInRange( "monitor_distance", 64, 16, 1024 ); } - private static final FileNotFoundAction MAKE_DIRECTORIES = (file, configFormat) -> { - Files.createDirectories(file.getParent()); - Files.createFile(file); - configFormat.initEmptyFile(file); + private static final FileNotFoundAction MAKE_DIRECTORIES = ( file, configFormat ) -> { + Files.createDirectories( file.getParent() ); + Files.createFile( file ); + configFormat.initEmptyFile( file ); return false; }; - private static CommentedFileConfig buildFileConfig(Path path) { - return CommentedFileConfig.builder(path) - .onFileNotFound(MAKE_DIRECTORIES) - .preserveInsertionOrder() - .build(); + private static CommentedFileConfig buildFileConfig( Path path ) + { + return CommentedFileConfig.builder( path ) + .onFileNotFound( MAKE_DIRECTORIES ) + .preserveInsertionOrder() + .build(); } - public static void serverStarting(MinecraftServer server) { - Path serverPath = server.getSavePath(serverDir).resolve(serverFileName); + public static void serverStarting( MinecraftServer server ) + { + Path serverPath = server.getSavePath( serverDir ).resolve( serverFileName ); - try(CommentedFileConfig config = buildFileConfig(serverPath)) { + try( CommentedFileConfig config = buildFileConfig( serverPath ) ) + { config.load(); - serverSpec.correct(config, Config::correctionListener); + serverSpec.correct( config, Config::correctionListener ); config.save(); serverConfig = config; sync(); } } - public static void serverStopping(MinecraftServer server) { + public static void serverStopping( MinecraftServer server ) + { serverConfig = null; } - public static void clientStarted(MinecraftClient client) { - try (CommentedFileConfig config = buildFileConfig(clientPath)) { + public static void clientStarted( MinecraftClient client ) + { + try( CommentedFileConfig config = buildFileConfig( clientPath ) ) + { config.load(); - clientSpec.correct(config, Config::correctionListener); + clientSpec.correct( config, Config::correctionListener ); config.save(); clientConfig = config; sync(); } } - private static void correctionListener(ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue) { - String key = String.join(".", path); - switch(action) { + private static void correctionListener( ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue ) + { + String key = String.join( ".", path ); + switch( action ) + { case ADD: - ComputerCraft.log.warn("Config key {} missing -> added default value.", key); break; + ComputerCraft.log.warn( "Config key {} missing -> added default value.", key ); + break; case REMOVE: - ComputerCraft.log.warn("Config key {} not defined -> removed from config.", key); break; + ComputerCraft.log.warn( "Config key {} not defined -> removed from config.", key ); + break; case REPLACE: - ComputerCraft.log.warn("Config key {} not valid -> replaced with default value.", key); + ComputerCraft.log.warn( "Config key {} not valid -> replaced with default value.", key ); } } - public static void sync() { - if(serverConfig != null) { + public static void sync() + { + if( serverConfig != null ) + { // General - ComputerCraft.computerSpaceLimit = serverConfig.get("computer_space_limit"); - ComputerCraft.floppySpaceLimit = serverConfig.get("floppy_space_limit"); - ComputerCraft.maximumFilesOpen = serverConfig.get("maximum_open_files"); - ComputerCraft.disableLua51Features = serverConfig.get("disable_lua51_features"); - ComputerCraft.defaultComputerSettings = serverConfig.get("default_computer_settings"); - ComputerCraft.debugEnable = serverConfig.get("debug_enabled"); - ComputerCraft.logComputerErrors = serverConfig.get("log_computer_errors"); - ComputerCraft.commandRequireCreative = serverConfig.get("command_require_creative"); + ComputerCraft.computerSpaceLimit = serverConfig.get( "computer_space_limit" ); + ComputerCraft.floppySpaceLimit = serverConfig.get( "floppy_space_limit" ); + ComputerCraft.maximumFilesOpen = serverConfig.get( "maximum_open_files" ); + ComputerCraft.disableLua51Features = serverConfig.get( "disable_lua51_features" ); + ComputerCraft.defaultComputerSettings = serverConfig.get( "default_computer_settings" ); + ComputerCraft.debugEnable = serverConfig.get( "debug_enabled" ); + ComputerCraft.logComputerErrors = serverConfig.get( "log_computer_errors" ); + ComputerCraft.commandRequireCreative = serverConfig.get( "command_require_creative" ); // Execution - ComputerCraft.computerThreads = serverConfig.get("execution.computer_threads"); - ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_global_time")); - ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_computer_time")); + ComputerCraft.computerThreads = serverConfig.get( "execution.computer_threads" ); + ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_global_time" ) ); + ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_computer_time" ) ); // HTTP - ComputerCraft.httpEnabled = serverConfig.get("http.enabled"); - ComputerCraft.httpWebsocketEnabled = serverConfig.get("http.websocket_enabled"); - ComputerCraft.httpRules = serverConfig.>get("http.rules").stream().map(AddressRuleConfig::parseRule) - .filter(Objects::nonNull).collect(Collectors.toList()); - ComputerCraft.httpMaxRequests = serverConfig.get("http.max_requests"); - ComputerCraft.httpMaxWebsockets = serverConfig.get("http.max_websockets"); + ComputerCraft.httpEnabled = serverConfig.get( "http.enabled" ); + ComputerCraft.httpWebsocketEnabled = serverConfig.get( "http.websocket_enabled" ); + ComputerCraft.httpRules = serverConfig.>get( "http.rules" ).stream().map( AddressRuleConfig::parseRule ) + .filter( Objects::nonNull ).collect( Collectors.toList() ); + ComputerCraft.httpMaxRequests = serverConfig.get( "http.max_requests" ); + ComputerCraft.httpMaxWebsockets = serverConfig.get( "http.max_websockets" ); // Peripherals - ComputerCraft.enableCommandBlock = serverConfig.get("peripheral.command_block_enabled"); - ComputerCraft.modemRange = serverConfig.get("peripheral.modem_range"); - ComputerCraft.modemHighAltitudeRange = serverConfig.get("peripheral.modem_high_altitude_range"); - ComputerCraft.modemRangeDuringStorm = serverConfig.get("peripheral.modem_range_during_storm"); - ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get("peripheral.modem_high_altitude_range_during_storm"); - ComputerCraft.maxNotesPerTick = serverConfig.get("peripheral.max_notes_per_tick"); - ComputerCraft.monitorBandwidth = serverConfig.get("peripheral.monitor_bandwidth"); + ComputerCraft.enableCommandBlock = serverConfig.get( "peripheral.command_block_enabled" ); + ComputerCraft.modemRange = serverConfig.get( "peripheral.modem_range" ); + ComputerCraft.modemHighAltitudeRange = serverConfig.get( "peripheral.modem_high_altitude_range" ); + ComputerCraft.modemRangeDuringStorm = serverConfig.get( "peripheral.modem_range_during_storm" ); + ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get( "peripheral.modem_high_altitude_range_during_storm" ); + ComputerCraft.maxNotesPerTick = serverConfig.get( "peripheral.max_notes_per_tick" ); + ComputerCraft.monitorBandwidth = serverConfig.get( "peripheral.monitor_bandwidth" ); // Turtles - ComputerCraft.turtlesNeedFuel = serverConfig.get("turtle.need_fuel"); - ComputerCraft.turtleFuelLimit = serverConfig.get("turtle.normal_fuel_limit"); - ComputerCraft.advancedTurtleFuelLimit = serverConfig.get("turtle.advanced_fuel_limit"); - ComputerCraft.turtlesObeyBlockProtection = serverConfig.get("turtle.obey_block_protection"); - ComputerCraft.turtlesCanPush = serverConfig.get("turtle.can_push"); + ComputerCraft.turtlesNeedFuel = serverConfig.get( "turtle.need_fuel" ); + ComputerCraft.turtleFuelLimit = serverConfig.get( "turtle.normal_fuel_limit" ); + ComputerCraft.advancedTurtleFuelLimit = serverConfig.get( "turtle.advanced_fuel_limit" ); + ComputerCraft.turtlesObeyBlockProtection = serverConfig.get( "turtle.obey_block_protection" ); + ComputerCraft.turtlesCanPush = serverConfig.get( "turtle.can_push" ); ComputerCraft.turtleDisabledActions.clear(); - for(String value : serverConfig.>get("turtle.disabled_actions")) { - ComputerCraft.turtleDisabledActions.add(getAction(value)); + for( String value : serverConfig.>get( "turtle.disabled_actions" ) ) + { + ComputerCraft.turtleDisabledActions.add( getAction( value ) ); } // Terminal Size - ComputerCraft.computerTermWidth = serverConfig.get("term_sizes.computer.width"); - ComputerCraft.computerTermHeight = serverConfig.get("term_sizes.computer.height"); - ComputerCraft.pocketTermWidth = serverConfig.get("term_sizes.pocket_computer.width"); - ComputerCraft.pocketTermHeight = serverConfig.get("term_sizes.pocket_computer.height"); - ComputerCraft.monitorWidth = serverConfig.get("term_sizes.monitor.width"); - ComputerCraft.monitorHeight = serverConfig.get("term_sizes.monitor.height"); + ComputerCraft.computerTermWidth = serverConfig.get( "term_sizes.computer.width" ); + ComputerCraft.computerTermHeight = serverConfig.get( "term_sizes.computer.height" ); + ComputerCraft.pocketTermWidth = serverConfig.get( "term_sizes.pocket_computer.width" ); + ComputerCraft.pocketTermHeight = serverConfig.get( "term_sizes.pocket_computer.height" ); + ComputerCraft.monitorWidth = serverConfig.get( "term_sizes.monitor.width" ); + ComputerCraft.monitorHeight = serverConfig.get( "term_sizes.monitor.height" ); } // Client - if(clientConfig != null) { - ComputerCraft.monitorRenderer = clientConfig.getEnum("monitor_renderer", MonitorRenderer.class); - int distance = clientConfig.get("monitor_distance"); + if( clientConfig != null ) + { + ComputerCraft.monitorRenderer = clientConfig.getEnum( "monitor_renderer", MonitorRenderer.class ); + int distance = clientConfig.get( "monitor_distance" ); ComputerCraft.monitorDistanceSq = distance * distance; } } - private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE); + private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo( CaseFormat.UPPER_UNDERSCORE ); - private static TurtleAction getAction(String value) { - try { - return TurtleAction.valueOf(converter.convert(value)); + private static TurtleAction getAction( String value ) + { + try + { + return TurtleAction.valueOf( converter.convert( value ) ); } - catch(IllegalArgumentException e) { + catch( IllegalArgumentException e ) + { return null; } } From 0bf7f3de89309bdc7165b28c697068c71c7bb6d6 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 9 Jun 2021 09:04:40 +0100 Subject: [PATCH 6/8] Final checkstyle cleanup --- .../computercraft/api/turtle/FakePlayer.java | 144 +++++++++++++----- .../computercraft/client/FrameInfo.java | 5 - .../client/render/CableHighlightRenderer.java | 5 - .../client/render/ItemMapLikeRenderer.java | 12 +- .../render/MonitorHighlightRenderer.java | 5 +- .../render/TileEntityTurtleRenderer.java | 14 +- .../client/render/TurtleModelLoader.java | 5 +- .../computercraft/core/asm/Generator.java | 5 +- .../fabric/mixin/MixinBlock.java | 2 + .../fabric/mixin/MixinEntity.java | 2 + .../fabric/mixin/MixinHeldItemRenderer.java | 8 +- .../mixin/MixinItemFrameEntityRenderer.java | 6 +- .../fabric/mixin/MixinServerWorld.java | 2 + .../fabric/mixin/WorldSavePathAccess.java | 5 +- .../shared/computer/apis/CommandAPI.java | 29 +--- .../shared/computer/core/InputHandler.java | 41 +---- .../shared/network/NetworkHandler.java | 3 + .../commandblock/CommandBlockPeripheral.java | 5 +- .../peripheral/diskdrive/BlockDiskDrive.java | 5 +- .../peripheral/monitor/TileMonitor.java | 4 +- .../peripheral/printer/BlockPrinter.java | 3 +- .../peripheral/printer/PrinterPeripheral.java | 10 +- .../peripheral/printer/TilePrinter.java | 4 +- .../shared/pocket/apis/PocketAPI.java | 20 +-- .../shared/turtle/apis/TurtleAPI.java | 31 ++-- .../shared/turtle/recipes/TurtleRecipe.java | 3 +- .../turtle/recipes/TurtleUpgradeRecipe.java | 5 +- .../shared/util/CommentedConfigSpec.java | 3 +- .../computercraft/shared/util/Config.java | 2 +- .../computercraft/shared/util/IDAssigner.java | 4 +- 30 files changed, 199 insertions(+), 193 deletions(-) diff --git a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java index f1cfd1790..d36eef98c 100644 --- a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java +++ b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java @@ -59,19 +59,29 @@ public class FakePlayer extends ServerPlayerEntity // region Direct networkHandler access @Override - public void enterCombat() { } + public void enterCombat() + { + } @Override - public void endCombat() { } + public void endCombat() + { + } @Override - public void tick() { } + public void tick() + { + } @Override - public void playerTick() { } + public void playerTick() + { + } @Override - public void onDeath( DamageSource damage ) { } + public void onDeath( DamageSource damage ) + { + } @Override public Entity moveToWorld( ServerWorld destination ) @@ -92,10 +102,14 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void stopRiding() { } + public void stopRiding() + { + } @Override - public void openEditSignScreen( SignBlockEntity tile ) { } + public void openEditSignScreen( SignBlockEntity tile ) + { + } @Override public OptionalInt openHandledScreen( @Nullable NamedScreenHandlerFactory container ) @@ -104,31 +118,49 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void sendTradeOffers( int id, TradeOfferList list, int level, int experience, boolean levelled, boolean refreshable ) { } + public void sendTradeOffers( int id, TradeOfferList list, int level, int experience, boolean levelled, boolean refreshable ) + { + } @Override - public void openHorseInventory( HorseBaseEntity horse, Inventory inventory ) { } + public void openHorseInventory( HorseBaseEntity horse, Inventory inventory ) + { + } @Override - public void openEditBookScreen( ItemStack stack, Hand hand ) { } + public void openEditBookScreen( ItemStack stack, Hand hand ) + { + } @Override - public void openCommandBlockScreen( CommandBlockBlockEntity block ) { } + public void openCommandBlockScreen( CommandBlockBlockEntity block ) + { + } @Override - public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack ) { } + public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack ) + { + } @Override - public void onHandlerRegistered( ScreenHandler container, DefaultedList defaultedList ) { } + public void onHandlerRegistered( ScreenHandler container, DefaultedList defaultedList ) + { + } @Override - public void onPropertyUpdate( ScreenHandler container, int key, int value ) { } + public void onPropertyUpdate( ScreenHandler container, int key, int value ) + { + } @Override - public void closeHandledScreen() { } + public void closeHandledScreen() + { + } @Override - public void updateCursorStack() { } + public void updateCursorStack() + { + } @Override public int unlockRecipes( Collection> recipes ) @@ -144,31 +176,49 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void sendMessage( Text textComponent, boolean status ) { } + public void sendMessage( Text textComponent, boolean status ) + { + } @Override - protected void consumeItem() { } + protected void consumeItem() + { + } @Override - public void lookAt( EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d ) {} + public void lookAt( EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d ) + { + } @Override - public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) { } + public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) + { + } @Override - protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance ) { } + protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance ) + { + } @Override - protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles ) { } + protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles ) + { + } @Override - protected void onStatusEffectRemoved( StatusEffectInstance statusEffectInstance ) { } + protected void onStatusEffectRemoved( StatusEffectInstance statusEffectInstance ) + { + } @Override - public void requestTeleport( double x, double y, double z ) { } + public void requestTeleport( double x, double y, double z ) + { + } @Override - public void setGameMode( GameMode gameMode ) { } + public void setGameMode( GameMode gameMode ) + { + } @Override public void sendMessage( Text message, MessageType type, UUID senderUuid ) @@ -183,25 +233,39 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void sendResourcePackUrl( String url, String hash ) { } + public void sendResourcePackUrl( String url, String hash ) + { + } @Override - public void onStoppedTracking( Entity entity ) { } + public void onStoppedTracking( Entity entity ) + { + } @Override - public void setCameraEntity( Entity entity ) { } + public void setCameraEntity( Entity entity ) + { + } @Override - public void teleport( ServerWorld serverWorld, double x, double y, double z, float pitch, float yaw ) { } + 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 ) { } + public void sendInitialChunkPackets( ChunkPos chunkPos, Packet packet, Packet packet2 ) + { + } @Override - public void sendUnloadChunkPacket( ChunkPos chunkPos ) { } + public void sendUnloadChunkPacket( ChunkPos chunkPos ) + { + } @Override - public void playSound( SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch ) { } + public void playSound( SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch ) + { + } private static class FakeNetHandler extends ServerPlayNetworkHandler { @@ -211,16 +275,24 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void disconnect( Text message ) { } + public void disconnect( Text message ) + { + } @Override - public void onVehicleMove( VehicleMoveC2SPacket move ) { } + public void onVehicleMove( VehicleMoveC2SPacket move ) + { + } @Override - public void onRequestCommandCompletions( RequestCommandCompletionsC2SPacket packet ) { } + public void onRequestCommandCompletions( RequestCommandCompletionsC2SPacket packet ) + { + } @Override - public void sendPacket( Packet packet, @Nullable GenericFutureListener> listener ) { } + public void sendPacket( Packet packet, @Nullable GenericFutureListener> listener ) + { + } } private static class FakeConnection extends ClientConnection diff --git a/src/main/java/dan200/computercraft/client/FrameInfo.java b/src/main/java/dan200/computercraft/client/FrameInfo.java index 7afc250e9..600f44e05 100644 --- a/src/main/java/dan200/computercraft/client/FrameInfo.java +++ b/src/main/java/dan200/computercraft/client/FrameInfo.java @@ -13,11 +13,6 @@ public final class FrameInfo private static int tick; private static long renderFrame; - static - { - - } - private FrameInfo() { } diff --git a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java index 1c1190d1f..2532e044f 100644 --- a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java @@ -22,7 +22,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.World; @Environment( EnvType.CLIENT ) public final class CableHighlightRenderer @@ -31,13 +30,9 @@ public final class CableHighlightRenderer { } - /** - * Draw an outline for a specific part of a cable "Multipart". - */ public static boolean drawHighlight( MatrixStack stack, VertexConsumer consumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState state ) { - World world = entity.getEntityWorld(); Camera info = MinecraftClient.getInstance().gameRenderer.getCamera(); // We only care about instances with both cable and modem. diff --git a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java index 502ebce10..7d3fb152b 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java @@ -23,14 +23,15 @@ import net.minecraft.util.math.MathHelper; @Environment( EnvType.CLIENT ) public abstract class ItemMapLikeRenderer { - public void renderItemFirstPerson( MatrixStack transform, VertexConsumerProvider render, int lightTexture, Hand hand, float pitch, float equipProgress - , float swingProgress, ItemStack stack ) + public void renderItemFirstPerson( + MatrixStack transform, VertexConsumerProvider render, int lightTexture, Hand hand, float pitch, float equipProgress, + float swingProgress, ItemStack stack + ) { PlayerEntity player = MinecraftClient.getInstance().player; transform.push(); - if( hand == Hand.MAIN_HAND && player.getOffHandStack() - .isEmpty() ) + if( hand == Hand.MAIN_HAND && player.getOffHandStack().isEmpty() ) { this.renderItemFirstPersonCenter( transform, render, lightTexture, pitch, equipProgress, swingProgress, stack ); } @@ -39,8 +40,7 @@ public abstract class ItemMapLikeRenderer this.renderItemFirstPersonSide( transform, render, lightTexture, - hand == Hand.MAIN_HAND ? player.getMainArm() : player.getMainArm() - .getOpposite(), + hand == Hand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(), equipProgress, swingProgress, stack ); diff --git a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java index 2a5d0e570..d0117b2ac 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java @@ -36,8 +36,9 @@ public final class MonitorHighlightRenderer { } - public static boolean drawHighlight( MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos - , BlockState blockState ) + public static boolean drawHighlight( + MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState + ) { // Preserve normal behaviour when crouching. if( entity.isInSneakingPose() ) diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java index c657decd7..e788540db 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java @@ -99,21 +99,11 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer float f2 = (float) (tint & 255) / 255.0F; buffer.quad( matrix, bakedquad, - new float[] { - 1.0F, - 1.0F, - 1.0F, - 1.0F - }, + new float[] { 1.0F, 1.0F, 1.0F, 1.0F }, f, f1, f2, - new int[] { - lightmapCoord, - lightmapCoord, - lightmapCoord, - lightmapCoord - }, + new int[] { lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord }, overlayLight, true ); } diff --git a/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java b/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java index 50ae22c5b..2012b4b17 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java @@ -67,7 +67,10 @@ public final class TurtleModelLoader { private final Identifier family; - private TurtleModel( Identifier family ) {this.family = family;} + private TurtleModel( Identifier family ) + { + this.family = family; + } @Override public Collection getTextureDependencies( Function modelGetter, diff --git a/src/main/java/dan200/computercraft/core/asm/Generator.java b/src/main/java/dan200/computercraft/core/asm/Generator.java index c630b140f..cdc966044 100644 --- a/src/main/java/dan200/computercraft/core/asm/Generator.java +++ b/src/main/java/dan200/computercraft/core/asm/Generator.java @@ -11,7 +11,10 @@ import com.google.common.cache.LoadingCache; import com.google.common.primitives.Primitives; import com.google.common.reflect.TypeToken; import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.*; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java index 0dd5c35f1..05ed3bde3 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java @@ -16,6 +16,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; /** + * Captures block drops. + * * @see Block#dropStack(World, BlockPos, ItemStack) */ @Mixin( Block.class ) diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java index baee509b6..5bb1671b9 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java @@ -15,6 +15,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** + * Captures entities. + * * @see Entity#dropStack(ItemStack, float) */ @Mixin( Entity.class ) diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java index 675ecbaff..4573b1bd2 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java @@ -45,9 +45,11 @@ public class MixinHeldItemRenderer "Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At( "HEAD" ), cancellable = true ) - public void renderFirstPersonItem_Injected( AbstractClientPlayerEntity player, float var2, float pitch, Hand hand, float swingProgress, - ItemStack stack, float equipProgress, MatrixStack matrixStack, VertexConsumerProvider provider, int light, - CallbackInfo callback ) + public void renderFirstPersonItem( + AbstractClientPlayerEntity player, float var2, float pitch, Hand hand, float swingProgress, + ItemStack stack, float equipProgress, MatrixStack matrixStack, VertexConsumerProvider provider, int light, + CallbackInfo callback + ) { if( stack.getItem() instanceof ItemPrintout ) { diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java index a63706f37..47364d858 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java @@ -24,8 +24,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public class MixinItemFrameEntityRenderer { @Inject( method = "render", at = @At( "HEAD" ), cancellable = true ) - private void renderItem_Injected( ItemFrameEntity itemFrameEntity, float f, float g, MatrixStack matrixStack, - VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo info ) + private void renderItem( + ItemFrameEntity itemFrameEntity, float f, float g, MatrixStack matrixStack, + VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo info + ) { ItemStack stack = itemFrameEntity.getHeldItemStack(); if( stack.getItem() instanceof ItemPrintout ) diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java index ab08f7b2e..8d1d79e37 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinServerWorld.java @@ -14,6 +14,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** + * Captures item stacks spawned into the world. + * * @see ServerWorld#spawnEntity(Entity) */ @Mixin( ServerWorld.class ) diff --git a/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java index 4c78d0161..fcaff65cf 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java @@ -13,5 +13,8 @@ import org.spongepowered.asm.mixin.gen.Invoker; public interface WorldSavePathAccess { @Invoker( "" ) - static WorldSavePath createWorldSavePath( String relativePath ) { throw new UnsupportedOperationException(); } + static WorldSavePath createWorldSavePath( String relativePath ) + { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java index dd52f0bb0..b76d8704a 100644 --- a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java +++ b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java @@ -70,10 +70,7 @@ public class CommandAPI implements ILuaAPI .getServer(); if( server == null || !server.areCommandBlocksEnabled() ) { - return new Object[] { - false, - createOutput( "Command blocks disabled by server" ) - }; + return new Object[] { false, createOutput( "Command blocks disabled by server" ) }; } CommandManager commandManager = server.getCommandManager(); @@ -82,11 +79,7 @@ public class CommandAPI implements ILuaAPI { receiver.clearOutput(); int result = commandManager.execute( this.computer.getSource(), command ); - return new Object[] { - result > 0, - receiver.copyOutput(), - result - }; + return new Object[] { result > 0, receiver.copyOutput(), result }; } catch( Throwable t ) { @@ -94,10 +87,7 @@ public class CommandAPI implements ILuaAPI { ComputerCraft.log.error( "Error running command.", t ); } - return new Object[] { - false, - createOutput( "Java Exception Thrown: " + t ) - }; + return new Object[] { false, createOutput( "Java Exception Thrown: " + t ) }; } } @@ -187,11 +177,7 @@ public class CommandAPI implements ILuaAPI { // This is probably safe to do on the Lua thread. Probably. BlockPos pos = this.computer.getPos(); - return new Object[] { - pos.getX(), - pos.getY(), - pos.getZ() - }; + return new Object[] { pos.getX(), pos.getY(), pos.getZ() }; } /** @@ -252,14 +238,11 @@ public class CommandAPI implements ILuaAPI Block block = state.getBlock(); Map table = new HashMap<>(); - table.put( "name", - Registry.BLOCK.getId( block ) - .toString() ); + table.put( "name", Registry.BLOCK.getId( block ).toString() ); table.put( "world", world.getRegistryKey() ); Map stateTable = new HashMap<>(); - for( ImmutableMap.Entry, Comparable> entry : state.getEntries() - .entrySet() ) + for( ImmutableMap.Entry, Comparable> entry : state.getEntries().entrySet() ) { Property property = entry.getKey(); stateTable.put( property.getName(), getPropertyValue( property, entry.getValue() ) ); diff --git a/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java b/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java index 7cc9bd2ba..c7b630720 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/InputHandler.java @@ -3,7 +3,6 @@ * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.computer.core; /** @@ -14,59 +13,35 @@ package dan200.computercraft.shared.computer.core; */ public interface InputHandler { + void queueEvent( String event, Object[] arguments ); + default void keyDown( int key, boolean repeat ) { - this.queueEvent( "key", - new Object[] { - key, - repeat - } ); + queueEvent( "key", new Object[] { key, repeat } ); } - void queueEvent( String event, Object[] arguments ); - default void keyUp( int key ) { - this.queueEvent( "key_up", new Object[] { key } ); + queueEvent( "key_up", new Object[] { key } ); } default void mouseClick( int button, int x, int y ) { - this.queueEvent( "mouse_click", - new Object[] { - button, - x, - y - } ); + queueEvent( "mouse_click", new Object[] { button, x, y } ); } default void mouseUp( int button, int x, int y ) { - this.queueEvent( "mouse_up", - new Object[] { - button, - x, - y - } ); + queueEvent( "mouse_up", new Object[] { button, x, y } ); } default void mouseDrag( int button, int x, int y ) { - this.queueEvent( "mouse_drag", - new Object[] { - button, - x, - y - } ); + queueEvent( "mouse_drag", new Object[] { button, x, y } ); } default void mouseScroll( int direction, int x, int y ) { - this.queueEvent( "mouse_scroll", - new Object[] { - direction, - x, - y - } ); + queueEvent( "mouse_scroll", new Object[] { direction, x, y } ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java b/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java index cf99a32be..91b2e92b0 100644 --- a/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java +++ b/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java @@ -80,6 +80,7 @@ public final class NetworkHandler /** * /** Register packet, and a thread-unsafe handler for it. * + * @param The type of the packet to send. * @param id The identifier for this packet type * @param factory The factory for this type of packet. */ @@ -95,6 +96,8 @@ public final class NetworkHandler /** * /** Register packet, and a thread-unsafe handler for it. * + * @param The type of the packet to send. + * @param type The class of the type of packet to send. * @param id The identifier for this packet type * @param decoder The factory for this type of packet. */ diff --git a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java index 722f2a993..9b9b78bb8 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java @@ -95,9 +95,6 @@ public class CommandBlockPeripheral implements IPeripheral .execute( this.commandBlock.getWorld() ); int result = this.commandBlock.getCommandExecutor() .getSuccessCount(); - return result > 0 ? new Object[] { true } : new Object[] { - false, - "Command failed" - }; + return result > 0 ? new Object[] { true } : new Object[] { false, "Command failed" }; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java index 2eb7fd0b4..238ea300e 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java @@ -51,8 +51,9 @@ public class BlockDiskDrive extends BlockGeneric } @Override - public void afterBreak( @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te - , @Nonnull ItemStack stack ) + public void afterBreak( + @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te, @Nonnull ItemStack stack + ) { if( te instanceof Nameable && ((Nameable) te).hasCustomName() ) { diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java index fca06c392..e398b3356 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java @@ -654,9 +654,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile @SuppressWarnings( "StatementWithEmptyBody" ) void expand() { - while( this.mergeLeft() || this.mergeRight() || this.mergeUp() || this.mergeDown() ) - { - } + while( this.mergeLeft() || this.mergeRight() || this.mergeUp() || this.mergeDown() ) ; } void contractNeighbours() diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java index a9f91b35b..e8d4bfc56 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java @@ -53,8 +53,7 @@ public class BlockPrinter extends BlockGeneric } @Override - public void afterBreak( @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te - , @Nonnull ItemStack stack ) + public void afterBreak( @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te, @Nonnull ItemStack stack ) { if( te instanceof Nameable && ((Nameable) te).hasCustomName() ) { diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java index e0cb64942..a1dfdb3bd 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java @@ -97,10 +97,7 @@ public class PrinterPeripheral implements IPeripheral Terminal page = this.getCurrentPage(); int x = page.getCursorX(); int y = page.getCursorY(); - return new Object[] { - x + 1, - y + 1 - }; + return new Object[] { x + 1, y + 1 }; } /** @@ -131,10 +128,7 @@ public class PrinterPeripheral implements IPeripheral Terminal page = this.getCurrentPage(); int width = page.getWidth(); int height = page.getHeight(); - return new Object[] { - width, - height - }; + return new Object[] { width, height }; } /** diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java index 32afe0839..78fd08741 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -52,7 +52,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent 9, 10, 11, - 12 + 12, }; private static final int[] TOP_SLOTS = new int[] { 1, @@ -60,7 +60,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent 3, 4, 5, - 6 + 6, }; private static final int[] SIDE_SLOTS = new int[] { 0 }; private final DefaultedList inventory = DefaultedList.ofSize( SLOTS, ItemStack.EMPTY ); diff --git a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java index 55b9168b6..e6f27a8d4 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java +++ b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java @@ -65,10 +65,7 @@ public class PocketAPI implements ILuaAPI Entity entity = this.computer.getEntity(); if( !(entity instanceof PlayerEntity) ) { - return new Object[] { - false, - "Cannot find player" - }; + return new Object[] { false, "Cannot find player" }; } PlayerEntity player = (PlayerEntity) entity; PlayerInventory inventory = player.inventory; @@ -83,10 +80,7 @@ public class PocketAPI implements ILuaAPI } if( newUpgrade == null ) { - return new Object[] { - false, - "Cannot find a valid upgrade" - }; + return new Object[] { false, "Cannot find a valid upgrade" }; } // Remove the current upgrade @@ -146,10 +140,7 @@ public class PocketAPI implements ILuaAPI Entity entity = this.computer.getEntity(); if( !(entity instanceof PlayerEntity) ) { - return new Object[] { - false, - "Cannot find player" - }; + return new Object[] { false, "Cannot find player" }; } PlayerEntity player = (PlayerEntity) entity; PlayerInventory inventory = player.inventory; @@ -157,10 +148,7 @@ public class PocketAPI implements ILuaAPI if( previousUpgrade == null ) { - return new Object[] { - false, - "Nothing to unequip" - }; + return new Object[] { false, "Nothing to unequip" }; } this.computer.setUpgrade( null ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java index f577bac63..200a21c84 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -523,8 +523,8 @@ public class TurtleAPI implements ILuaAPI * Get the maximum amount of fuel this turtle currently holds. * * @return The fuel level, or "unlimited". - * @cc.treturn[1] number The current amount of fuel a turtle this turtle has. - * @cc.treturn[2] "unlimited" If turtles do not consume fuel when moving. + * @cc.treturn [1] number The current amount of fuel a turtle this turtle has. + * @cc.treturn [2] "unlimited" If turtles do not consume fuel when moving. * @see #getFuelLimit() * @see #refuel(Optional) */ @@ -547,9 +547,9 @@ public class TurtleAPI implements ILuaAPI * @param countA The maximum number of items to consume. One can pass `0` to check if an item is combustable or not. * @return If this turtle could be refuelled. * @throws LuaException If the refuel count is out of range. - * @cc.treturn[1] true If the turtle was refuelled. - * @cc.treturn[2] false If the turtle was not refuelled. - * @cc.treturn[2] string The reason the turtle was not refuelled ( + * @cc.treturn [1] true If the turtle was refuelled. + * @cc.treturn [2] false If the turtle was not refuelled. + * @cc.treturn [2] string The reason the turtle was not refuelled ( * @cc.usage Refuel a turtle from the currently selected slot. *
    {@code
          * local level = turtle.getFuelLevel()
    @@ -631,8 +631,8 @@ public class TurtleAPI implements ILuaAPI
          * By default, normal turtles have a limit of 20,000 and advanced turtles of 100,000.
          *
          * @return The limit, or "unlimited".
    -     * @cc.treturn[1] number The maximum amount of fuel a turtle can hold.
    -     * @cc.treturn[2] "unlimited" If turtles do not consume fuel when moving.
    +     * @cc.treturn [1] number The maximum amount of fuel a turtle can hold.
    +     * @cc.treturn [2] "unlimited" If turtles do not consume fuel when moving.
          * @see #getFuelLevel()
          * @see #refuel(Optional)
          */
    @@ -650,9 +650,9 @@ public class TurtleAPI implements ILuaAPI
          * upgrade is removed, but no new one is equipped.
          *
          * @return Whether an item was equiped or not.
    -     * @cc.treturn[1] true If the item was equipped.
    -     * @cc.treturn[2] false If we could not equip the item.
    -     * @cc.treturn[2] string The reason equipping this item failed.
    +     * @cc.treturn [1] true If the item was equipped.
    +     * @cc.treturn [2] false If we could not equip the item.
    +     * @cc.treturn [2] string The reason equipping this item failed.
          * @see #equipRight()
          */
         @LuaFunction
    @@ -669,9 +669,9 @@ public class TurtleAPI implements ILuaAPI
          * upgrade is removed, but no new one is equipped.
          *
          * @return Whether an item was equiped or not.
    -     * @cc.treturn[1] true If the item was equipped.
    -     * @cc.treturn[2] false If we could not equip the item.
    -     * @cc.treturn[2] string The reason equipping this item failed.
    +     * @cc.treturn [1] true If the item was equipped.
    +     * @cc.treturn [2] false If we could not equip the item.
    +     * @cc.treturn [2] string The reason equipping this item failed.
          * @see #equipRight()
          */
         @LuaFunction
    @@ -776,10 +776,7 @@ public class TurtleAPI implements ILuaAPI
             TurtleActionEvent event = new TurtleInspectItemEvent( this.turtle, stack, table, detailed );
             if( TurtleEvent.post( event ) )
             {
    -            return new Object[] {
    -                false,
    -                event.getFailureMessage()
    -            };
    +            return new Object[] { false, event.getFailureMessage() };
             }
     
             return new Object[] { table };
    diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java
    index 4df8575fb..75e97d9df 100644
    --- a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java
    +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java
    @@ -24,8 +24,7 @@ public final class TurtleRecipe extends ComputerFamilyRecipe
             new dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe.Serializer()
             {
                 @Override
    -            protected TurtleRecipe create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result
    -                , ComputerFamily family )
    +            protected TurtleRecipe create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, ComputerFamily family )
                 {
                     return new TurtleRecipe( identifier, group, width, height, ingredients, result, family );
                 }
    diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java
    index da301a48a..cbaace61e 100644
    --- a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java
    +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java
    @@ -144,10 +144,7 @@ public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe
             };
     
             // Get the upgrades for the new items
    -        ItemStack[] items = new ItemStack[] {
    -            rightItem,
    -            leftItem
    -        };
    +        ItemStack[] items = new ItemStack[] { rightItem, leftItem };
             for( int i = 0; i < 2; i++ )
             {
                 if( !items[i].isEmpty() )
    diff --git a/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java b/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java
    index fe13c12ba..6401f7f39 100644
    --- a/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java
    +++ b/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java
    @@ -31,7 +31,8 @@ public class CommentedConfigSpec extends ConfigSpec
     
         public int correct( Config config )
         {
    -        return correct( config, ( action, path, incorrectValue, correctedValue ) -> {} );
    +        return correct( config, ( action, path, incorrectValue, correctedValue ) -> {
    +        } );
         }
     
         public int correct( Config config, ConfigSpec.CorrectionListener listener )
    diff --git a/src/main/java/dan200/computercraft/shared/util/Config.java b/src/main/java/dan200/computercraft/shared/util/Config.java
    index b9fc34156..a6b14af07 100644
    --- a/src/main/java/dan200/computercraft/shared/util/Config.java
    +++ b/src/main/java/dan200/computercraft/shared/util/Config.java
    @@ -30,7 +30,7 @@ import java.util.*;
     import java.util.concurrent.TimeUnit;
     import java.util.stream.Collectors;
     
    -public class Config
    +public final class Config
     {
         private static final int MODEM_MAX_RANGE = 100000;
     
    diff --git a/src/main/java/dan200/computercraft/shared/util/IDAssigner.java b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java
    index b50822b6c..6a10e44fa 100644
    --- a/src/main/java/dan200/computercraft/shared/util/IDAssigner.java
    +++ b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java
    @@ -31,7 +31,9 @@ public final class IDAssigner
         private static final WorldSavePath FOLDER = WorldSavePathAccess.createWorldSavePath( ComputerCraft.MOD_ID );
         private static final Gson GSON = new GsonBuilder().setPrettyPrinting()
             .create();
    -    private static final Type ID_TOKEN = new TypeToken>() {}.getType();
    +    private static final Type ID_TOKEN = new TypeToken>()
    +    {
    +    }.getType();
         private static Map ids;
         private static WeakReference server;
         private static Path idFile;
    
    From e8d90b94ecc8e9d7f40fd5893d175448c8b6518e Mon Sep 17 00:00:00 2001
    From: Jonathan Coates 
    Date: Wed, 9 Jun 2021 09:13:37 +0100
    Subject: [PATCH 7/8] Woops
    
    ---
     .github/ISSUE_TEMPLATE/bug_report.md | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
    index f9cee6d08..042f1f27a 100644
    --- a/.github/ISSUE_TEMPLATE/bug_report.md
    +++ b/.github/ISSUE_TEMPLATE/bug_report.md
    @@ -11,6 +11,6 @@ labels: bug
     
     ## Useful information to include:
      - Minecraft version
    - - CC: Tweaked version
    + - CC: Restitched version
      - Logs: These will be located in the `logs/` directory of your Minecraft instance. Please upload them as a gist or directly into this editor.
      - Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
    
    From 2279f5044de70c7811a4fffff06c65468e27a127 Mon Sep 17 00:00:00 2001
    From: Jonathan Coates 
    Date: Wed, 9 Jun 2021 09:19:21 +0100
    Subject: [PATCH 8/8] Nuke treasure disks
    
    They're datapacks now. Right???
    ---
     .github/ISSUE_TEMPLATE/peripheral_shoutout.md |    2 +-
     .github/workflows/main-ci.yml                 |    3 +
     .gitignore                                    |    2 +-
     .gitpod.Dockerfile                            |    2 +-
     .gitpod.yml                                   |    2 +-
     .vscode/settings.json                         |    6 +-
     LICENSE                                       |   14 +-
     README.md                                     |   14 +-
     codeInspectionSettings.xml                    |    2 +-
     codeStyleSettings.xml                         |    2 +-
     config/pre-commit/config.yml                  |    3 +-
     patchwork.md                                  |   32 +-
     .../computer_advanced_front_blink.png.mcmeta  |   12 +-
     .../computer_command_front_blink.png.mcmeta   |   12 +-
     .../computer_normal_front_blink.png.mcmeta    |   12 +-
     .../item/pocket_computer_blink.png.mcmeta     |   12 +-
     .../recipes/computercraft/cable.json          |    2 +-
     .../computercraft/computer_advanced.json      |    2 +-
     .../computercraft/computer_command.json       |    2 +-
     .../recipes/computercraft/disk_1.json         |    2 +-
     .../recipes/computercraft/disk_10.json        |    2 +-
     .../recipes/computercraft/disk_11.json        |    2 +-
     .../recipes/computercraft/disk_12.json        |    2 +-
     .../recipes/computercraft/disk_13.json        |    2 +-
     .../recipes/computercraft/disk_14.json        |    2 +-
     .../recipes/computercraft/disk_15.json        |    2 +-
     .../recipes/computercraft/disk_16.json        |    2 +-
     .../recipes/computercraft/disk_2.json         |    2 +-
     .../recipes/computercraft/disk_3.json         |    2 +-
     .../recipes/computercraft/disk_4.json         |    2 +-
     .../recipes/computercraft/disk_5.json         |    2 +-
     .../recipes/computercraft/disk_6.json         |    2 +-
     .../recipes/computercraft/disk_7.json         |    2 +-
     .../recipes/computercraft/disk_8.json         |    2 +-
     .../recipes/computercraft/disk_9.json         |    2 +-
     .../recipes/computercraft/disk_drive.json     |    2 +-
     .../computercraft/monitor_advanced.json       |    2 +-
     .../recipes/computercraft/monitor_normal.json |    2 +-
     .../computercraft/speaker.json                |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../minecraft/diamond_axe.json                |    2 +-
     .../minecraft/diamond_hoe.json                |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../pocket_computer_advanced.json             |    2 +-
     .../computercraft/pocket_computer_normal.json |    2 +-
     .../pocket_normal/computercraft/speaker.json  |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../pocket_normal/minecraft/diamond_axe.json  |    2 +-
     .../pocket_normal/minecraft/diamond_hoe.json  |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../recipes/computercraft/printer.json        |    2 +-
     .../recipes/computercraft/speaker.json        |    2 +-
     .../computercraft/speaker.json                |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../minecraft/diamond_axe.json                |    2 +-
     .../minecraft/diamond_hoe.json                |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../turtle_normal/computercraft/speaker.json  |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../turtle_normal/minecraft/diamond_axe.json  |    2 +-
     .../turtle_normal/minecraft/diamond_hoe.json  |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../recipes/computercraft/wired_modem.json    |    2 +-
     .../computercraft/wired_modem_full_from.json  |    2 +-
     .../computercraft/wired_modem_full_to.json    |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../loot_tables/blocks/computer_advanced.json |    2 +-
     .../loot_tables/blocks/computer_command.json  |    2 +-
     .../loot_tables/blocks/computer_normal.json   |    2 +-
     .../loot_tables/blocks/disk_drive.json        |    2 +-
     .../loot_tables/blocks/monitor_advanced.json  |    2 +-
     .../loot_tables/blocks/monitor_normal.json    |    2 +-
     .../loot_tables/blocks/printer.json           |    2 +-
     .../loot_tables/blocks/speaker.json           |    2 +-
     .../loot_tables/blocks/turtle_advanced.json   |    2 +-
     .../loot_tables/blocks/turtle_normal.json     |    2 +-
     .../loot_tables/blocks/wired_modem_full.json  |    2 +-
     .../blocks/wireless_modem_advanced.json       |    2 +-
     .../blocks/wireless_modem_normal.json         |    2 +-
     .../loot_tables/treasure_disk.json            |    2 +-
     .../computercraft/lua/rom/autorun/.ignoreme   |    2 +-
     .../computercraft/lua/rom/help/whatsnew.txt   |    2 +-
     .../GopherAtl/battleship/battleship.lua       |  875 ------
     .../treasure/GravityScore/LuaIDE/luaide.lua   | 2212 ---------------
     .../lua/treasure/JTK/maze3d/maze2d.lua        |  327 ---
     .../lua/treasure/JTK/maze3d/maze3d.lua        |  614 ----
     .../lua/treasure/Lyqyd/nsh/framebuffer.lua    |  159 --
     .../lua/treasure/Lyqyd/nsh/get.lua            |   26 -
     .../lua/treasure/Lyqyd/nsh/nsh.lua            |  721 -----
     .../lua/treasure/Lyqyd/nsh/put.lua            |   35 -
     .../TheOriginalBIT/tictactoe/tictactoe.lua    |  444 ---
     .../dan200/alongtimeago/alongtimeago.lua      |   47 -
     .../deprecated/GopherAtl/talk/talk.lua        |    1 -
     .../fredthead/protector/protector.lua         | 1311 ---------
     .../nitrogenfingers/goldrunner/goldrunner.lua | 1314 ---------
     .../goldrunner/levels/01_welcome              |   18 -
     .../goldrunner/levels/02_coalmine             |   18 -
     .../goldrunner/levels/03_seeker               |   18 -
     .../goldrunner/levels/04_fortress             |   18 -
     .../goldrunner/levels/05_caged                |   18 -
     .../goldrunner/levels/06_flowers              |   18 -
     .../goldrunner/levels/07_pyramid              |   18 -
     .../goldrunner/levels/08_cavein               |   18 -
     .../goldrunner/levels/09_skyislands           |   18 -
     .../goldrunner/levels/10_convert              |   16 -
     .../nitrogenfingers/npaintpro/3dprint.lua     |  119 -
     .../nitrogenfingers/npaintpro/gameutils.lua   |  615 ----
     .../nitrogenfingers/npaintpro/npaintpro.lua   | 2517 -----------------
     .../treasure/vilsol/gameoflife/gameoflife.lua |  178 --
     .../computercraft/speaker.json                |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../minecraft/diamond_axe.json                |    2 +-
     .../minecraft/diamond_hoe.json                |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../pocket_normal/computercraft/speaker.json  |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../pocket_normal/minecraft/diamond_axe.json  |    2 +-
     .../pocket_normal/minecraft/diamond_hoe.json  |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../computercraft/speaker.json                |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../minecraft/diamond_axe.json                |    2 +-
     .../minecraft/diamond_hoe.json                |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../minecraft/netherite_pickaxe.json          |    2 +-
     .../turtle_normal/computercraft/speaker.json  |    2 +-
     .../wireless_modem_advanced.json              |    2 +-
     .../computercraft/wireless_modem_normal.json  |    2 +-
     .../minecraft/crafting_table.json             |    2 +-
     .../turtle_normal/minecraft/diamond_axe.json  |    2 +-
     .../turtle_normal/minecraft/diamond_hoe.json  |    2 +-
     .../minecraft/diamond_pickaxe.json            |    2 +-
     .../minecraft/diamond_shovel.json             |    2 +-
     .../minecraft/diamond_sword.json              |    2 +-
     .../minecraft/netherite_pickaxe.json          |    2 +-
     .../recipes/wired_modem_full_from.json        |    2 +-
     .../recipes/wired_modem_full_to.json          |    2 +-
     .../computercraft/tags/items/computer.json    |    2 +-
     .../computercraft/tags/items/monitor.json     |    2 +-
     .../data/computercraft/tags/items/turtle.json |    2 +-
     .../computercraft/tags/items/wired_modem.json |    2 +-
     .../minecraft/tags/items/piglin_loved.json    |    2 +-
     tools/disk_recipe.json                        |   10 -
     tools/language.lua                            |  120 -
     tools/language.py                             |   43 +
     tools/parse-reports.py                        |  114 +
     tools/pocket_upgrade_advancement.json         |   22 -
     tools/pocket_upgrade_recipe.json              |   13 -
     tools/recipes.lua                             |  136 -
     tools/turtle_upgrade_advancement.json         |   22 -
     tools/turtle_upgrade_recipe.json              |   12 -
     180 files changed, 353 insertions(+), 12220 deletions(-)
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/GopherAtl/battleship/battleship.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/GravityScore/LuaIDE/luaide.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/JTK/maze3d/maze2d.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/JTK/maze3d/maze3d.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/Lyqyd/nsh/framebuffer.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/Lyqyd/nsh/get.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/Lyqyd/nsh/nsh.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/Lyqyd/nsh/put.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/TheOriginalBIT/tictactoe/tictactoe.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/dan200/alongtimeago/alongtimeago.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/deprecated/GopherAtl/talk/talk.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/fredthead/protector/protector.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/goldrunner.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/01_welcome
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/02_coalmine
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/03_seeker
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/04_fortress
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/05_caged
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/06_flowers
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/07_pyramid
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/08_cavein
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/09_skyislands
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/10_convert
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/npaintpro/3dprint.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/npaintpro/gameutils.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/nitrogenfingers/npaintpro/npaintpro.lua
     delete mode 100644 src/main/resources/data/computercraft/lua/treasure/vilsol/gameoflife/gameoflife.lua
     delete mode 100644 tools/disk_recipe.json
     delete mode 100644 tools/language.lua
     create mode 100755 tools/language.py
     create mode 100755 tools/parse-reports.py
     delete mode 100644 tools/pocket_upgrade_advancement.json
     delete mode 100644 tools/pocket_upgrade_recipe.json
     delete mode 100644 tools/recipes.lua
     delete mode 100644 tools/turtle_upgrade_advancement.json
     delete mode 100644 tools/turtle_upgrade_recipe.json
    
    diff --git a/.github/ISSUE_TEMPLATE/peripheral_shoutout.md b/.github/ISSUE_TEMPLATE/peripheral_shoutout.md
    index e2aa86bb7..2d2c9c139 100644
    --- a/.github/ISSUE_TEMPLATE/peripheral_shoutout.md
    +++ b/.github/ISSUE_TEMPLATE/peripheral_shoutout.md
    @@ -9,4 +9,4 @@ labels: peripheralShoutout
      - Link to the mod
      - Mod Name
      - Basic description of the mod
    - - Link to CC:R Peripheral Documentation for the mod
    \ No newline at end of file
    + - Link to CC:R Peripheral Documentation for the mod
    diff --git a/.github/workflows/main-ci.yml b/.github/workflows/main-ci.yml
    index a144e94db..c1103486c 100644
    --- a/.github/workflows/main-ci.yml
    +++ b/.github/workflows/main-ci.yml
    @@ -9,6 +9,9 @@ jobs:
     
         steps:
         - uses: actions/checkout@v2
    +    - name: Checkout submodules
    +      run: git submodule update --init --recursive
    +
     
         - name: Set up Java 8
           uses: actions/setup-java@v1
    diff --git a/.gitignore b/.gitignore
    index 015269e79..4efc71fe5 100644
    --- a/.gitignore
    +++ b/.gitignore
    @@ -20,4 +20,4 @@
     .idea
     .gradle
     *.DS_Store
    -.project
    \ No newline at end of file
    +.project
    diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile
    index a42c8bdb1..7a0de01ca 100644
    --- a/.gitpod.Dockerfile
    +++ b/.gitpod.Dockerfile
    @@ -16,4 +16,4 @@ RUN sudo apt-get -q update && \
         sudo apt install -yq openjdk-8-jdk openjdk-16-jdk
     
     # This is so that you can use java 8 until such a time as you switch to java 16
    -RUN sudo update-java-alternatives --set java-1.8.0-openjdk-amd64
    \ No newline at end of file
    +RUN sudo update-java-alternatives --set java-1.8.0-openjdk-amd64
    diff --git a/.gitpod.yml b/.gitpod.yml
    index 0e926b2a1..d773abea4 100644
    --- a/.gitpod.yml
    +++ b/.gitpod.yml
    @@ -15,4 +15,4 @@ vscode:
     
     
     tasks:
    -  - init: ./gradlew
    \ No newline at end of file
    +  - init: ./gradlew
    diff --git a/.vscode/settings.json b/.vscode/settings.json
    index f1a1f60c9..1ffa4a6e4 100644
    --- a/.vscode/settings.json
    +++ b/.vscode/settings.json
    @@ -9,7 +9,7 @@
     		// Custom Hidden Files
     		"**/.bin": true,
     		"**/.editorconfig": true,
    -    },	
    -	
    +    },
    +
     	"java.configuration.updateBuildConfiguration": "automatic"
    -}
    \ No newline at end of file
    +}
    diff --git a/LICENSE b/LICENSE
    index 65a70f5ae..cf30d77a6 100644
    --- a/LICENSE
    +++ b/LICENSE
    @@ -19,14 +19,14 @@ Mod: The mod code designated by the present license, in source form, binary
     form, as obtained standalone, as part of a wider distribution or resulting from
     the compilation of the original or modified sources.
     
    -Dependency: Code required for the mod to work properly. This includes 
    +Dependency: Code required for the mod to work properly. This includes
     dependencies required to compile the code as well as any file or modification
     that is explicitly or implicitly required for the mod to be working.
     
     1. Scope
     --------
     
    -The present license is granted to any user of the mod. As a prerequisite, 
    +The present license is granted to any user of the mod. As a prerequisite,
     a user must own a legally acquired copy of Minecraft
     
     2. Liability
    @@ -41,13 +41,13 @@ or misuse of this mod fall on the user.
     3. Play rights
     --------------
     
    -The user is allowed to install this mod on a Minecraft client or server and to play 
    +The user is allowed to install this mod on a Minecraft client or server and to play
     without restriction.
     
     4. Modification rights
     ----------------------
     
    -The user has the right to decompile the source code, look at either the 
    +The user has the right to decompile the source code, look at either the
     decompiled version or the original source code, and to modify it.
     
     5. Distribution of original or modified copy rights
    @@ -61,10 +61,10 @@ include:
        - patch to its source or binary files
        - any copy of a portion of its binary source files
     
    -The user is allowed to redistribute this mod partially, in totality, or 
    +The user is allowed to redistribute this mod partially, in totality, or
     included in a distribution.
     
    -When distributing binary files, the user must provide means to obtain its 
    +When distributing binary files, the user must provide means to obtain its
     entire set of sources or modified sources at no cost.
     
     All distributions of this mod must remain licensed under the CCPL.
    @@ -92,7 +92,7 @@ must be made available at no cost and remain licensed under the CCPL.
     ---------------
     
     If you choose to contribute code or assets to be included in this mod, you
    -agree that, if added to to the main repository at 
    +agree that, if added to to the main repository at
     https://github.com/dan200/ComputerCraft, your contributions will be covered by
     this license, and that Daniel Ratcliffe will retain the right to re-license the
     mod, including your contributions, in part or in whole, under other licenses.
    diff --git a/README.md b/README.md
    index d13e01b6a..0041dfb86 100644
    --- a/README.md
    +++ b/README.md
    @@ -30,7 +30,7 @@ Any contribution is welcome, be that using the mod, reporting bugs or contributi
     	> 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
    @@ -38,29 +38,29 @@ Any contribution is welcome, be that using the mod, reporting bugs or contributi
     	> 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, 
    +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.
     
     ## 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) 
    +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)
     
     ## 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]
    ~~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)`.~~ +* [Fixed (d10f297c): please report if bug persists]
    ~~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 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! \ No newline at end of file + * This is an example mod for how to make peripherals that work as a block, or as a turtle upgrade! diff --git a/codeInspectionSettings.xml b/codeInspectionSettings.xml index 2862d72b4..57b8ed0d7 100644 --- a/codeInspectionSettings.xml +++ b/codeInspectionSettings.xml @@ -2488,4 +2488,4 @@ - \ No newline at end of file + diff --git a/codeStyleSettings.xml b/codeStyleSettings.xml index b4c9573fd..9a1e0f1d4 100644 --- a/codeStyleSettings.xml +++ b/codeStyleSettings.xml @@ -58,4 +58,4 @@