simple-tech

Minecraft: Better than Adventure! mod that adds simple blocks to automate tasks
git clone git://memoryshards.xyz/simple-tech.git
Log | Files | Refs | README | LICENSE

commit 40e608d5aef3ccfae4de42ea9f749c227eb3da61
Author: Amb0s <ambos@disroot.org>
Date:   Fri, 18 Aug 2023 21:07:28 +0200

Initial public commit

Diffstat:
A.gitignore | 40++++++++++++++++++++++++++++++++++++++++
ALICENSE | 361+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME.md | 11+++++++++++
Abuild.gradle | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Agradle.properties | 15+++++++++++++++
Agradle/wrapper/gradle-wrapper.jar | 0
Agradle/wrapper/gradle-wrapper.properties | 5+++++
Agradlew | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Agradlew.bat | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asettings.gradle | 18++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/SimpleTech.java | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/BlockAllocator.java | 392+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/BlockFan.java | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/BlockJumpPad.java | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/BlockLightSensor.java | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/BlockTrappedChest.java | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/entity/TileEntityAllocator.java | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/entity/TileEntityFan.java | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/block/entity/TileEntityLightSensor.java | 29+++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/gui/GuiAllocator.java | 36++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/mixin/MinecraftMixin.java | 20++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/mixin/RenderBlocksMixin.java | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/turniplabs/simpletech/player/inventory/ContainerAllocator.java | 47+++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/resources/assets/simpletech/block/allocator_back.png | 0
Asrc/main/resources/assets/simpletech/block/allocator_back_top_bottom.png | 0
Asrc/main/resources/assets/simpletech/block/allocator_front.png | 0
Asrc/main/resources/assets/simpletech/block/allocator_front_top_bottom.png | 0
Asrc/main/resources/assets/simpletech/block/fan_front.png | 0
Asrc/main/resources/assets/simpletech/block/fan_front_powered.png | 0
Asrc/main/resources/assets/simpletech/block/jump_pad.png | 0
Asrc/main/resources/assets/simpletech/block/light_sensor.png | 0
Asrc/main/resources/assets/simpletech/block/misc_side.png | 0
Asrc/main/resources/assets/simpletech/block/misc_top_bottom.png | 0
Asrc/main/resources/assets/simpletech/gui/allocator.png | 0
Asrc/main/resources/fabric.mod.json | 30++++++++++++++++++++++++++++++
Asrc/main/resources/lang/simpletech/en_US.lang | 13+++++++++++++
Asrc/main/resources/lang/simpletech/fr_FR.lang | 13+++++++++++++
Asrc/main/resources/simpletech.mixins.json | 15+++++++++++++++
38 files changed, 2214 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,40 @@ +# gradle + +.gradle/ +build/ +out/ +classes/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +bin/ +.classpath +.project + +# macos + +*.DS_Store + +# fabric + +run/ +run-server/ +libs/*.jar + +# misc + +archive/ +TODO.md diff --git a/LICENSE b/LICENSE @@ -0,0 +1,360 @@ +Creative Commons Legal Code + +Attribution-NonCommercial-ShareAlike 3.0 Unported + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR + DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(g) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined above) for the purposes of this + License. + c. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + d. "License Elements" means the following high-level license attributes + as selected by Licensor and indicated in the title of this License: + Attribution, Noncommercial, ShareAlike. + e. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + f. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + g. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + h. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + i. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + j. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights in +other media and formats. Subject to Section 8(f), all rights not expressly +granted by Licensor are hereby reserved, including but not limited to the +rights described in Section 4(e). + +4. Restrictions. The license granted in Section 3 above is expressly made +subject to and limited by the following restrictions: + + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(d), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(d), as requested. + b. You may Distribute or Publicly Perform an Adaptation only under: (i) + the terms of this License; (ii) a later version of this License with + the same License Elements as this License; (iii) a Creative Commons + jurisdiction license (either this or a later license version) that + contains the same License Elements as this License (e.g., + Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). + You must include a copy of, or the URI, for Applicable License with + every copy of each Adaptation You Distribute or Publicly Perform. You + may not offer or impose any terms on the Adaptation that restrict the + terms of the Applicable License or the ability of the recipient of the + Adaptation to exercise the rights granted to that recipient under the + terms of the Applicable License. You must keep intact all notices that + refer to the Applicable License and to the disclaimer of warranties + with every copy of the Work as included in the Adaptation You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Adaptation, You may not impose any effective technological + measures on the Adaptation that restrict the ability of a recipient of + the Adaptation from You to exercise the rights granted to that + recipient under the terms of the Applicable License. This Section 4(b) + applies to the Adaptation as incorporated in a Collection, but this + does not require the Collection apart from the Adaptation itself to be + made subject to the terms of the Applicable License. + c. You may not exercise any of the rights granted to You in Section 3 + above in any manner that is primarily intended for or directed toward + commercial advantage or private monetary compensation. The exchange of + the Work for other copyrighted works by means of digital file-sharing + or otherwise shall not be considered to be intended for or directed + toward commercial advantage or private monetary compensation, provided + there is no payment of any monetary compensation in con-nection with + the exchange of copyrighted works. + d. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and, (iv) consistent with Section 3(b), in the case of an Adaptation, + a credit identifying the use of the Work in the Adaptation (e.g., + "French translation of the Work by Original Author," or "Screenplay + based on original Work by Original Author"). The credit required by + this Section 4(d) may be implemented in any reasonable manner; + provided, however, that in the case of a Adaptation or Collection, at + a minimum such credit will appear, if a credit for all contributing + authors of the Adaptation or Collection appears, then as part of these + credits and in a manner at least as prominent as the credits for the + other contributing authors. For the avoidance of doubt, You may only + use the credit required by this Section for the purpose of attribution + in the manner set out above and, by exercising Your rights under this + License, You may not implicitly or explicitly assert or imply any + connection with, sponsorship or endorsement by the Original Author, + Licensor and/or Attribution Parties, as appropriate, of You or Your + use of the Work, without the separate, express prior written + permission of the Original Author, Licensor and/or Attribution + Parties. + e. For the avoidance of doubt: + + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor reserves + the exclusive right to collect such royalties for any exercise by + You of the rights granted under this License if Your exercise of + such rights is for a purpose or use which is otherwise than + noncommercial as permitted under Section 4(c) and otherwise waives + the right to collect royalties through any statutory or compulsory + licensing scheme; and, + iii. Voluntary License Schemes. The Licensor reserves the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License that is for a + purpose or use which is otherwise than noncommercial as permitted + under Section 4(c). + f. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE +FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS +AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE +WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT +LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, +ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT +DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED +WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + +8. Miscellaneous + + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + + +Creative Commons Notice + + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of this License. + + Creative Commons may be contacted at https://creativecommons.org/. +\ No newline at end of file diff --git a/README.md b/README.md @@ -0,0 +1,11 @@ +# Simple Tech + +## Additions +* Pfaeff's mod items (fan, jump pad, light sensor, allocator) + +## Instructions + +Check the [BTA! wiki page about modding](https://bta.miraheze.org/wiki/Modding) + +## Credits +Pfaeff, for their [mod](http://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/1272572-v1-5-1-pfaeffs-mod-ssp-v1-2-3-allocator-jump-pad), licensed under [Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB), which inspired me to make this one (some features were changed). diff --git a/build.gradle b/build.gradle @@ -0,0 +1,116 @@ +plugins { + id 'babric-loom' version '1.1.+' + id 'java' +} + +group = project.mod_group +archivesBaseName = project.mod_name +version = project.mod_version + +loom { + gluedMinecraftJar() + noIntermediateMappings() + customMinecraftManifest.set("https://github.com/Turnip-Labs/bta-manifest-repo/releases/download/v${project.bta_version}/${project.bta_version}.json") +} + +repositories { + mavenCentral() + maven { + name = 'Babric' + url = 'https://maven.glass-launcher.net/babric' + } + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + ivy { + url = "https://github.com/Better-than-Adventure" + patternLayout { + artifact "[organisation]/releases/download/v[revision]/[module].jar" + m2compatible = true + } + metadataSources { artifact() } + } + ivy { + url = "https://github.com/Turnip-Labs" + patternLayout { + artifact "[organisation]/releases/download/v[revision]/[module]-[revision].jar" + m2compatible = true + } + metadataSources { artifact() } + } + ivy { + url = "https://github.com/Turnip-Labs" + patternLayout { + artifact "[organisation]/releases/download/[revision]/[module]-bta-[revision].jar" + m2compatible = true + } + metadataSources { artifact() } + } + ivy { + url = "https://piston-data.mojang.com" + patternLayout { + artifact "v1/[organisation]/[revision]/[module].jar" + m2compatible = true + } + metadataSources { artifact() } + } + ivy { + url = "https://github.com/MartinSVK12" + patternLayout { + artifact "[organisation]/releases/download/[revision]/[module]-[revision].jar" + m2compatible = true + } + metadataSources { artifact() } + } +} + +dependencies { + minecraft "bta-download-repo:bta:${project.bta_version}" + mappings loom.layered() {} + + modRuntimeOnly "objects:client:43db9b498cb67058d2e12d394e6507722e71bb45" // https://piston-data.mojang.com/v1/objects/43db9b498cb67058d2e12d394e6507722e71bb45/client.jar + modImplementation "fabric-loader:fabric-loader:${project.loader_version}" + + // Helper library + // If you do not need Halplibe you can comment this line out or delete this line + modImplementation "bta-halplibe:halplibe:${project.halplibe_version}" + + modImplementation "ModMenu:ModMenu:2.0.0" + + implementation "org.slf4j:slf4j-api:1.8.0-beta4" + implementation "org.apache.logging.log4j:log4j-slf4j18-impl:2.16.0" + + implementation 'com.google.guava:guava:30.0-jre' + implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.9' + + var log4jVersion = "2.20.0" + implementation("org.apache.logging.log4j:log4j-core:${log4jVersion}") + implementation("org.apache.logging.log4j:log4j-api:${log4jVersion}") + implementation("org.apache.logging.log4j:log4j-1.2-api:${log4jVersion}") + implementation("log4j:apache-log4j-extras:1.2.17") +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + withSourcesJar() +} + +tasks.withType(JavaCompile) { + options.release.set 8 +} + +jar { + from("LICENSE") { + rename { "${it}_${archivesBaseName}" } + } +} + +processResources { + inputs.property "version", version + + filesMatching("fabric.mod.json") { + expand "version": version + } +} diff --git a/gradle.properties b/gradle.properties @@ -0,0 +1,15 @@ +org.gradle.jvmargs=-Xmx2G + +# BTA +bta_version=1.7.7.0_01 + +# Loader +loader_version=0.14.19-babric.1-bta + +# HalpLibe +halplibe_version=2.1.1 + +# Mod +mod_version=0.1.0 +mod_group=turniplabs +mod_name=simple-tech diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar Binary files differ. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew @@ -0,0 +1,185 @@ +#!/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 +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +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='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MSYS* | MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +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 + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# 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 + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + 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" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +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" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat @@ -0,0 +1,89 @@ +@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 +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +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="-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 execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +: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 %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + maven { + name = 'Jitpack' + url = 'https://jitpack.io' + } + maven { + name = 'Babric' + url = 'https://maven.glass-launcher.net/babric' + } + } +} +\ No newline at end of file diff --git a/src/main/java/turniplabs/simpletech/SimpleTech.java b/src/main/java/turniplabs/simpletech/SimpleTech.java @@ -0,0 +1,165 @@ +package turniplabs.simpletech; + +import net.fabricmc.api.ModInitializer; +import net.minecraft.client.sound.block.BlockSounds; +import net.minecraft.core.block.Block; +import net.minecraft.core.block.material.Material; +import net.minecraft.core.block.tag.BlockTags; +import net.minecraft.core.item.Item; +import net.minecraft.core.util.helper.Direction; +import net.minecraft.core.world.World; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import turniplabs.halplibe.helper.BlockHelper; +import turniplabs.halplibe.helper.EntityHelper; +import turniplabs.halplibe.helper.RecipeHelper; +import turniplabs.simpletech.block.*; +import turniplabs.simpletech.block.entity.TileEntityAllocator; +import turniplabs.simpletech.block.entity.TileEntityFan; +import turniplabs.simpletech.block.entity.TileEntityLightSensor; + +public class SimpleTech implements ModInitializer { + public static final String MOD_ID = "simpletech"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); + public static final int FAN_RANGE = 4; + public static final int UNPOWERED_FAN_ID = 3789; + public static final int POWERED_FAN_ID = 3790; + public static final int JUMP_PAD_ID = 3791; + public static final int TRAPPED_CHEST_ID = 3792; + public static final int LIGHT_SENSOR_ID = 3793; + public static final int ALLOCATOR_ID = 3794; + + // Blocks + public static final Block unpoweredFan = BlockHelper.createBlock( + MOD_ID, new BlockFan("block.fan.unpowered", UNPOWERED_FAN_ID, Material.stone,false, + "misc_top_bottom.png","misc_side.png","fan_front.png"), + BlockSounds.STONE, 1.5f, 10.0f, 0.0f) + .withTags(BlockTags.MINEABLE_BY_PICKAXE); + public static final Block poweredFan = BlockHelper.createBlock( + MOD_ID, new BlockFan("block.fan.powered", POWERED_FAN_ID, Material.stone,true, + "misc_top_bottom.png","misc_side.png","fan_front_powered.png"), + BlockSounds.STONE, 1.5f, 10.0f, 0.0f) + .withTags(BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.MINEABLE_BY_PICKAXE); + public static final Block jumpPad = BlockHelper.createBlock( + MOD_ID, new BlockJumpPad("block.jumppad", JUMP_PAD_ID, Material.wood), + "jump_pad.png", BlockSounds.WOOD, 1.0f, 2.5f, 0.0f) + .withTags(BlockTags.MINEABLE_BY_AXE); + public static final Block trappedChest = BlockHelper.createBlock( + MOD_ID, new BlockTrappedChest("chest.trapped", TRAPPED_CHEST_ID, Material.wood), + BlockSounds.WOOD, 2.5f, 5.0f, 0.0f) + .withTags(BlockTags.FENCES_CONNECT, BlockTags.MINEABLE_BY_AXE); + public static final Block lightSensor = BlockHelper.createBlock( + MOD_ID, new BlockLightSensor("block.lightsensor", LIGHT_SENSOR_ID, Material.wood), + "light_sensor.png", BlockSounds.WOOD, 1.0f, 2.5f, 0.0f) + .withTags(BlockTags.MINEABLE_BY_AXE); + public static final Block allocator = BlockHelper.createBlock( + MOD_ID, new BlockAllocator("block.allocator", ALLOCATOR_ID, Material.stone, + "misc_top_bottom.png", "misc_side.png", "allocator_front.png", + "allocator_back.png", "allocator_front_top_bottom.png", + "allocator_back_top_bottom.png", true, true), + BlockSounds.STONE, 1.5f, 10.0f, 0.0f) + .withTags(BlockTags.MINEABLE_BY_PICKAXE); + + @Override + public void onInitialize() { + // Entities. + EntityHelper.createTileEntity(TileEntityFan.class, "Fan"); + EntityHelper.createTileEntity(TileEntityLightSensor.class, "Light Sensor"); + EntityHelper.createTileEntity(TileEntityAllocator.class, "Allocator"); + + // Recipes. + RecipeHelper.Crafting.createRecipe(unpoweredFan, 1, new Object[]{ + "CCC", + "CIC", + "CRC", + 'C', Block.cobbleStone, + 'I', Item.ingotIron, + 'R', Item.dustRedstone + }); + RecipeHelper.Crafting.createShapelessRecipe(jumpPad, 1, new Object[]{ + Item.slimeball, Block.slabPlanksOak + }); + RecipeHelper.Crafting.createShapelessRecipe(trappedChest, 1, new Object[]{ + Item.dustRedstone, Block.chestPlanksOak + }); + RecipeHelper.Crafting.createRecipe(lightSensor, 1, new Object[]{ + " G ", + " Q ", + " S ", + 'G', Block.glass, + 'Q', Item.quartz, + 'S', Block.slabPlanksOak + }); + RecipeHelper.Crafting.createRecipe(allocator, 1, new Object[]{ + "CRC", + "CGC", + "CRC", + 'C', Block.cobbleStone, + 'R', Item.dustRedstone, + 'G', Item.ingotGold, + }); + + LOGGER.info("Simple Tech initialized."); + } + + public static int getRedstoneFromMetadata(int metadata) { + return metadata >> 4; // or 3? + } + + public static int getDirectionFromMetadata(int metadata) { + return metadata & 7; + } + + public static int createMetadata(int direction, int redstone) { + return (redstone << 4) | direction; + } + + public static int getOppositeDirectionById(int i) { + return Direction.getDirectionById(i).getOpposite().getId(); + } + + public static int getDirectionX(World world, int x, int y, int z) { + int direction = world.getBlockMetadata(x, y, z); + int dx = 0; + + if (direction == Direction.WEST.getId()) { + dx = 1; + } + + if (direction == Direction.EAST.getId()) { + dx = -1; + } + + return dx; + } + + public static int getDirectionY(World world, int x, int y, int z) { + int direction = world.getBlockMetadata(x, y, z); + int dy = 0; + + if (direction == Direction.DOWN.getId()) { + dy = 1; + } + + if (direction == Direction.UP.getId()) { + dy = -1; + } + + return dy; + } + + public static int getDirectionZ(World world, int x, int y, int z) { + int direction = world.getBlockMetadata(x, y, z); + int dz = 0; + + if (direction == Direction.NORTH.getId()) { + dz = 1; + } + + if (direction == Direction.SOUTH.getId()) { + dz = -1; + } + + return dz; + } +} diff --git a/src/main/java/turniplabs/simpletech/block/BlockAllocator.java b/src/main/java/turniplabs/simpletech/block/BlockAllocator.java @@ -0,0 +1,392 @@ +package turniplabs.simpletech.block; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.block.Block; +import net.minecraft.core.block.BlockTileEntity; +import net.minecraft.core.block.entity.TileEntity; +import net.minecraft.core.block.entity.TileEntityChest; +import net.minecraft.core.block.entity.TileEntityFurnace; +import net.minecraft.core.block.material.Material; +import net.minecraft.core.entity.Entity; +import net.minecraft.core.entity.EntityItem; +import net.minecraft.core.entity.EntityLiving; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.entity.vehicle.EntityMinecart; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.player.inventory.IInventory; +import net.minecraft.core.player.inventory.InventoryLargeChest; +import net.minecraft.core.sound.SoundType; +import net.minecraft.core.util.helper.Direction; +import net.minecraft.core.util.helper.Side; +import net.minecraft.core.util.phys.AABB; +import net.minecraft.core.world.World; +import turniplabs.halplibe.helper.TextureHelper; +import turniplabs.simpletech.gui.GuiAllocator; +import turniplabs.simpletech.SimpleTech; +import turniplabs.simpletech.block.entity.TileEntityAllocator; + +import java.util.List; +import java.util.Random; + +public class BlockAllocator extends BlockTileEntity { + private final int[] top; + private final int[] side; + private final int[] front; + private final int[] back; + private final int[] backTopBottom; + private final int[] frontTopBottom; + private final boolean allowFiltering; + private final boolean subItemFiltering; + + public BlockAllocator(String key, int id, Material material, + String top, String side, String front, String back, + String frontTopBottom, String backTopBottom, + boolean allowFiltering, boolean subItemFiltering) { + super(key, id, material); + this.allowFiltering = allowFiltering; + this.subItemFiltering = subItemFiltering; + this.top = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, top); + this.side = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, side); + this.front = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, front); + this.back = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, back); + this.frontTopBottom = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, frontTopBottom); + this.backTopBottom = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, backTopBottom); + } + + public int[] getTop() { + return this.top; + } + + public int[] getBack() { + return this.back; + } + + public int[] getFront() { + return this.front; + } + + @Override + protected TileEntity getNewBlockEntity() { + return new TileEntityAllocator(); + } + + @Override + public boolean blockActivated(World world, int x, int y, int z, EntityPlayer player) { + if (!this.allowFiltering) { + return false; + } else if (world.isClientSide) { + return true; + } else { + TileEntityAllocator allocator = (TileEntityAllocator) world.getBlockTileEntity(x, y, z); + + if (allocator != null) { + Minecraft.getMinecraft(Minecraft.class).displayGuiScreen(new GuiAllocator(player.inventory, allocator)); + } + + return true; + } + } + + @Override + public void updateTick(World world, int x, int y, int z, Random rand) { + if (world.isBlockIndirectlyGettingPowered(x, y, z) || world.isBlockIndirectlyGettingPowered(x, y + 1, z)) { + this.allocateItems(world, x, y, z, rand); + } + } + + @Override + public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) { + if (blockId > 0 && Block.blocksList[blockId].canProvidePower() && + (world.isBlockIndirectlyGettingPowered(x, y, z) || + world.isBlockIndirectlyGettingPowered(x, y + 1, z))) { + world.scheduleBlockUpdate(x, y, z, this.id, this.tickRate()); + } + } + + @Override + public int tickRate() { + return 4; + } + + @Override + public void onBlockAdded(World world, int x, int y, int z) { + super.onBlockAdded(world, x, y, z); + } + + @Override + public int getBlockTextureFromSideAndMetadata(Side side, int meta) { + int direction = SimpleTech.getDirectionFromMetadata(meta); + + if (direction > 5) { + return texCoordToIndex(this.top[0], this.top[1]); + } else if (side.getId() == SimpleTech.getOppositeDirectionById(direction)) { + if (side.getId() == Side.TOP.getId() || side.getId() == Side.BOTTOM.getId()) { + return texCoordToIndex(this.backTopBottom[0], this.backTopBottom[1]); + } + return texCoordToIndex(this.back[0], this.back[1]); + } else if (side.getId() == direction) { + if (side.getId() == Side.TOP.getId() || side.getId() == Side.BOTTOM.getId()) { + return texCoordToIndex(this.frontTopBottom[0], this.frontTopBottom[1]); + } + return texCoordToIndex(this.front[0], this.front[1]); + } else { + if (side.getId() == Side.TOP.getId() || side.getId() == Side.BOTTOM.getId()) { + return texCoordToIndex(this.top[0], this.top[1]); + } else { + return texCoordToIndex(this.side[0], this.side[1]); + } + } + } + + @Override + public void onBlockPlaced(World world, int x, int y, int z, Side side, EntityLiving entity, double sideHeight) { + Direction placementDirection = entity.getPlacementDirection(side).getOpposite(); + world.setBlockMetadataWithNotify(x, y, z, placementDirection.getId()); + } + + public int getRandomItemFromContainer(IInventory inventory, Random rand, World world, int x, int y, int z) { + if (inventory == null) { + return -1; + } else { + int i = -1; + int j = 1; + + byte startAt = 0; + + if (inventory instanceof TileEntityFurnace) { + startAt = 2; + } + + for (int k = startAt; k < inventory.getSizeInventory(); ++k) { + if (inventory.getStackInSlot(k) != null && this.passesFilter(world, x, y, z, + inventory.getStackInSlot(k)) && rand.nextInt(j) == 0) { + i = k; + ++j; + } + } + + return i; + } + } + + protected IInventory containerAtPos(World world, int x, int y, int z) { + TileEntity tile = world.getBlockTileEntity(x, y, z); + return !(tile instanceof IInventory) ? null : this.getDoubleChest(world, x, y, z); + } + + protected boolean blockingCubeAtPos(World world, int x, int y, int z) { + int blockID = world.getBlockId(x, y, z); + boolean isOpaque = Block.opaqueCubeLookup[blockID]; + + return isOpaque || blockID == Block.glass.id || + blockID == Block.cactus.id || + blockID == Block.cake.id || + blockID == Block.blockSnow.id || + blockID == Block.mobspawner.id || + blockID == Block.fencePlanksOak.id; + } + + private void putItemInContainer(IInventory inventory, ItemStack item, int index) { + if (item != null) { + if (index >= 0) { + ItemStack stack = inventory.getStackInSlot(index); + + if (stack != null) { + stack.stackSize += item.stackSize; + inventory.setInventorySlotContents(index, stack); + } else { + inventory.setInventorySlotContents(index, item); + } + } + } + } + + private void dispenseItem(World world, int x, int y, int z, int dx, int dy, int dz, ItemStack item, Random rand) { + double d = (double) x + (double) dx * 0.5D + 0.5D; + double d1 = (double) y + (double) dy * 0.5D + 0.5D; + double d2 = (double) z + (double) dz * 0.5D + 0.5D; + double d3 = rand.nextDouble() * 0.1D + 0.2D; + + EntityItem entityItem = new EntityItem(world, d, d1, d2, item); + + // Item movement. + entityItem.xd = (double) dx * d3; + entityItem.yd = (double) dy * d3; + entityItem.zd = (double) dz * d3; + entityItem.xd += rand.nextGaussian() * (double) 0.0075F * 6.0D; + entityItem.yd += rand.nextGaussian() * (double) 0.0075F * 6.0D; + entityItem.xd += rand.nextGaussian() * (double) 0.0075F * 6.0D; + + world.entityJoinedWorld(entityItem); + world.playSoundEffect(SoundType.GUI_SOUNDS, x, y, z, "random.click", 1.0f, 1.0f); + + // Particle rendering. + for (int i = 0; i < 10; ++i) { + double d4 = rand.nextDouble() * 0.2D + 0.01D; + double d5 = d + (double) dx * 0.01D + (rand.nextDouble() - 0.5D) * (double) dz * 0.5D; + double d6 = d1 + (rand.nextDouble() - 0.5D) * 0.5D; + double d7 = d2 + (double) dz * 0.01D + (rand.nextDouble() - 0.5D) * (double) dx * 0.5D; + double d8 = (double) dx * d4 + rand.nextGaussian() * 0.01D; + double d9 = -0.03D + rand.nextGaussian() * 0.01D; + double d10 = (double) dz * d4 + rand.nextGaussian() * 0.01D; + + world.spawnParticle("smoke", d5, d6, d7, d8, d9, d10); + } + } + + private boolean outputItem(World world, int x, int y, int z, int dx, int dy, int dz, ItemStack item, Random rand) { + IInventory outputContainer = this.containerAtPos(world, x + dx, y + dy, z + dz); + + if (outputContainer == null) { + List<Entity> index = world.getEntitiesWithinAABB(IInventory.class, AABB.getBoundingBoxFromPool( + x + dx, y + dy, z + dz, x + dx + 1, y + dy + 1, z + dz + 1)); + + if (index.size() > 0 && (!(index.get(0) instanceof EntityMinecart) || + ((EntityMinecart) index.get(0)).minecartType == 1)) { + outputContainer = (IInventory) index.get(0); + } + } + + if (outputContainer == null) { + if (!this.blockingCubeAtPos(world, x + dx, y + dy, z + dz)) { + this.dispenseItem(world, x, y, z, dx, dy, dz, item, rand); + + return true; + } + } else { + int index1 = this.getFirstFreeInventorySlotOfKind(outputContainer, item); + + if (index1 >= 0) { + this.putItemInContainer(outputContainer, item, index1); + return true; + } + } + + return false; + } + + private IInventory getDoubleChest(World world, int x, int y, int z) { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + if (!(tileEntity instanceof TileEntityChest)) { + return tileEntity instanceof IInventory ? (IInventory) tileEntity : null; + } else { + int blockId = world.getBlockId(x, y, z); + + IInventory chest1 = (IInventory) world.getBlockTileEntity(x, y, z); + IInventory chest2; + + if (world.getBlockId(x + 1, y, z) == blockId) { + chest2 = (IInventory) world.getBlockTileEntity(x + 1, y, z); + + return new InventoryLargeChest("", chest1, chest2); + } else if (world.getBlockId(x - 1, y, z) == blockId) { + chest2 = (IInventory) world.getBlockTileEntity(x - 1, y, z); + + return new InventoryLargeChest("", chest2, chest1); + } else if (world.getBlockId(x, y, z + 1) == blockId) { + chest2 = (IInventory) world.getBlockTileEntity(x, y, z + 1); + + return new InventoryLargeChest("", chest1, chest2); + } else if (world.getBlockId(x, y, z - 1) == blockId) { + chest2 = (IInventory) world.getBlockTileEntity(x, y, z - 1); + + return new InventoryLargeChest("", chest2, chest1); + } else { + return chest1; + } + } + } + + private void allocateItems(World world, int x, int y, int z, Random rand) { + int dx = SimpleTech.getDirectionX(world, x, y, z); + int dy = SimpleTech.getDirectionY(world, x, y, z); + int dz = SimpleTech.getDirectionZ(world, x, y, z); + + IInventory inputContainer = this.containerAtPos(world, x - dx, y - dy, z - dz); + + List<Entity> entities; + + if (inputContainer == null) { + entities = world.getEntitiesWithinAABB(IInventory.class, AABB.getBoundingBoxFromPool( + x - dx, y - dy, z - dz, x - dx + 1, y - dy + 1, z - dz + 1)); + + if (entities.size() > 0 && (!(entities.get(0) instanceof EntityMinecart) || + ((EntityMinecart)entities.get(0)).minecartType == 1)) { + inputContainer = (IInventory) entities.get(0); + } + } + + int itemIndex; + if (inputContainer == null) { + entities = world.getEntitiesWithinAABB(EntityItem.class, AABB.getBoundingBoxFromPool( + x - dx, y - dy, z - dz, x - dx + 1, y - dy + 1, z - dz + 1)); + + for (itemIndex = 0; itemIndex < entities.size(); ++itemIndex) { + if (entities.get(itemIndex) instanceof EntityItem) { + EntityItem itemType = (EntityItem) entities.get(itemIndex); + + if (itemType.isAlive() && this.passesFilter(world, x, y, z, itemType.item) && + this.outputItem(world, x, y, z, dx, dy, dz, itemType.item, rand)) { + itemType.outOfWorld(); + } + } + } + } else { + itemIndex = this.getRandomItemFromContainer(inputContainer, rand, world, x, y, z); + + if (itemIndex >= 0) { + int itemDamage = inputContainer.getStackInSlot(itemIndex).getItemDamageForDisplay(); + + ItemStack item = new ItemStack(inputContainer.getStackInSlot(itemIndex) + .getItem(), 1, itemDamage); + + if (this.outputItem(world, x, y, z, dx, dy, dz, item, rand)) { + inputContainer.decrStackSize(itemIndex, 1); + } + } + } + } + + private int getFirstFreeInventorySlotOfKind(IInventory inventory, ItemStack item) { + int inventorySize = inventory.getSizeInventory(); + + if (inventory instanceof TileEntityFurnace) { + --inventorySize; + } + + for (int i = 0; i < inventorySize; ++i) { + boolean canStack = false; + + if (inventory.getStackInSlot(i) != null && inventory.getStackInSlot(i).itemID == item.itemID && + (!item.getItem().getHasSubtypes() || + inventory.getStackInSlot(i).getItemDamageForDisplay() == item.getItemDamageForDisplay())) { + canStack = inventory.getStackInSlot(i).stackSize <= item.getMaxStackSize() - item.stackSize; + } + + if (inventory.getStackInSlot(i) == null || canStack) { + return i; + } + } + + return -1; + } + + private boolean passesFilter(World world, int x, int y, int z, ItemStack item) { + if (!this.allowFiltering) { + return true; + } else { + TileEntityAllocator tileentityallocator = (TileEntityAllocator)world.getBlockTileEntity(x, y, z); + ItemStack filterItem = tileentityallocator.getStackInSlot(0); + if (filterItem == null) { + return true; + } else { + boolean filterSubItems = true; + if (this.subItemFiltering) { + filterSubItems = filterItem.getItemDamageForDisplay() == item.getItemDamageForDisplay(); + } + + return filterItem.itemID == item.getItem().id && filterSubItems; + } + } + } +} diff --git a/src/main/java/turniplabs/simpletech/block/BlockFan.java b/src/main/java/turniplabs/simpletech/block/BlockFan.java @@ -0,0 +1,117 @@ +package turniplabs.simpletech.block; + +import net.minecraft.core.block.BlockTileEntity; +import net.minecraft.core.block.entity.TileEntity; +import net.minecraft.core.block.material.Material; +import net.minecraft.core.entity.EntityLiving; +import net.minecraft.core.enums.EnumDropCause; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.util.helper.Direction; +import net.minecraft.core.util.helper.Side; +import net.minecraft.core.world.World; +import turniplabs.halplibe.helper.TextureHelper; +import turniplabs.simpletech.SimpleTech; +import turniplabs.simpletech.block.entity.TileEntityFan; + +import java.util.Random; + +public class BlockFan extends BlockTileEntity { + private final int[] topBottom; + private final int[] side; + private final int[] front; + private final boolean isPowered; + + public BlockFan(String key, int id, Material material, boolean isPowered, String topBottom, + String side, String front) { + super(key, id, material); + this.isPowered = isPowered; + this.topBottom = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, topBottom); + this.side = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, side); + this.front = TextureHelper.registerBlockTexture(SimpleTech.MOD_ID, front); + } + + @Override + public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, + TileEntity tileEntity) { + // Only drops unpowered fan when broken. + return dropCause != EnumDropCause.IMPROPER_TOOL ? new ItemStack[]{new ItemStack(SimpleTech.unpoweredFan)} : null; + } + + @Override + public int tickRate() { + return 2; + } + + @Override + public int getBlockTextureFromSideAndMetadata(Side side, int j) { + int direction = SimpleTech.getDirectionFromMetadata(j); + if (direction > Direction.EAST.getId()) { + // Defaults to top/bottom texture. + return texCoordToIndex(this.topBottom[0], this.topBottom[1]); + } else if (side.getId() == direction) { + return texCoordToIndex(this.front[0], this.front[1]); + } else { + if (side.getId() == Side.TOP.getId() || side.getId() == Side.BOTTOM.getId()) { + return texCoordToIndex(this.topBottom[0], this.topBottom[1]); + } else { + return texCoordToIndex(this.side[0], this.side[1]); + } + } + } + + @Override + public void randomDisplayTick(World world, int x, int y, int z, Random rand) { + // Particle rendering. + if (this.isPowered) { + int dx = -SimpleTech.getDirectionX(world, x, y, z); + int dy = -SimpleTech.getDirectionY(world, x, y, z); + int dz = -SimpleTech.getDirectionZ(world, x, y, z); + + for (int i = 1; i < 3; ++i) { + double rx = rand.nextDouble() - 0.5; + double ry = rand.nextDouble() - 0.5; + double rz = rand.nextDouble() - 0.5; + world.spawnParticle("smoke", + (double) (x + dx) + 0.5 + rx, + (double) (y + dy) + 0.5 + ry, + (double) (z + dz) + 0.5 + rz, + 0.2 * (double) dx, + 0.2 * (double) dy, + 0.2 * (double) dz + ); + } + } + } + + @Override + public void onNeighborBlockChange(World world, int x, int y, int z, int l) { + int direction; + + // If it's currently powered by redstone... + if (world.isBlockIndirectlyGettingPowered(x, y, z) || world.isBlockIndirectlyGettingPowered(x, y + 1, z)) { + // If it wasn't already powered... + if (!this.isPowered) { + // Replaces the unpowered fan by its powered counterpart. + direction = world.getBlockMetadata(x, y, z); + world.setBlockAndMetadataWithNotify(x, y, z, SimpleTech.POWERED_FAN_ID, direction); + } + + world.scheduleBlockUpdate(x, y, z, this.id, this.tickRate()); + } else if (this.isPowered) { + // Replaces the powered fan by its unpowered counterpart. + direction = world.getBlockMetadata(x, y, z); + world.setBlockAndMetadataWithNotify(x, y, z, SimpleTech.UNPOWERED_FAN_ID, direction); + } + } + + @Override + public void onBlockPlaced(World world, int x, int y, int z, Side side, EntityLiving entity, double sideHeight) { + Direction placementDirection = entity.getPlacementDirection(side).getOpposite(); + world.setBlockMetadataWithNotify(x, y, z, placementDirection.getId()); + } + + @Override + protected TileEntity getNewBlockEntity() { + return new TileEntityFan(); + } +} diff --git a/src/main/java/turniplabs/simpletech/block/BlockJumpPad.java b/src/main/java/turniplabs/simpletech/block/BlockJumpPad.java @@ -0,0 +1,56 @@ +package turniplabs.simpletech.block; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.material.Material; +import net.minecraft.core.entity.Entity; +import net.minecraft.core.entity.EntityItem; +import net.minecraft.core.entity.EntityLiving; +import net.minecraft.core.world.World; + +public class BlockJumpPad extends Block { + public BlockJumpPad(String key, int id, Material material) { + super(key, id, material); + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean canPlaceBlockAt(World world, int x, int y, int z) { + return world.isBlockOpaqueCube(x, y - 1, z); + } + + public void jump(Entity entity) { + if ((entity instanceof EntityLiving || entity instanceof EntityItem) && entity.yd < 1.0D) { + entity.yd = 0.0D; + entity.fallDistance = 0.0F; + entity.push(0.0D, 1.0D, 0.0D); + } + } + + @Override + public void onEntityWalking(World world, int x, int y, int z, Entity entity) { + this.jump(entity); + } + + @Override + public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) { + if (entity.y > (double) y) { + this.jump(entity); + } + } + + @Override + public void setBlockBoundsBasedOnState(World world, int x, int y, int z) { + // Sets block shape when placed. + this.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 0.25f, 1.0f); + } + + @Override + public void setBlockBoundsForItemRender() { + // Sets block shape when rendered inside containers. + this.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 0.25f, 1.0f); + } +} diff --git a/src/main/java/turniplabs/simpletech/block/BlockLightSensor.java b/src/main/java/turniplabs/simpletech/block/BlockLightSensor.java @@ -0,0 +1,92 @@ +package turniplabs.simpletech.block; + +import net.minecraft.core.block.BlockTileEntity; +import net.minecraft.core.block.entity.TileEntity; +import net.minecraft.core.block.material.Material; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.world.World; +import net.minecraft.core.world.WorldSource; +import turniplabs.simpletech.SimpleTech; +import turniplabs.simpletech.block.entity.TileEntityLightSensor; + +public class BlockLightSensor extends BlockTileEntity { + private boolean inverted; + public BlockLightSensor(String key, int id, Material material) { + super(key, id, material); + this.inverted = false; + } + + public boolean isInverted() { + return inverted; + } + + @Override + public boolean renderAsNormalBlock() { + return false; + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean canProvidePower() { + return true; + } + + @Override + public TileEntity getNewBlockEntity() { + return new TileEntityLightSensor(); + } + + @Override + public boolean isPoweringTo(WorldSource blockAccess, int x, int y, int z, int side) { + // Debug code to display metadata. + boolean debug = false; + if (debug) { + System.out.println("METADATA: " + Integer.toString( + blockAccess.getBlockMetadata(x, y, z), 2)); + System.out.println("DIRECTION: " + Integer.toString( + SimpleTech.getDirectionFromMetadata(blockAccess.getBlockMetadata(x, y, z)), 2)); + System.out.println("REDSTONE: " + Integer.toString(SimpleTech.getRedstoneFromMetadata( + blockAccess.getBlockMetadata(x, y, z)), 2)); + System.out.println("METADATA (recombined): " + Integer.toString(SimpleTech.createMetadata( + SimpleTech.getDirectionFromMetadata(blockAccess.getBlockMetadata(x, y, z)), + SimpleTech.getRedstoneFromMetadata(blockAccess.getBlockMetadata(x, y, z))), 2)); + } + + return SimpleTech.getRedstoneFromMetadata(blockAccess.getBlockMetadata(x, y, z)) > 0; + } + + @Override + public void setBlockBoundsBasedOnState(World world, int x, int y, int z) { + // Sets block shape when placed. + this.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 0.25f, 1.0f); + } + + @Override + public void setBlockBoundsForItemRender() { + // Sets block shape when rendered inside containers. + this.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 0.25f, 1.0f); + } + + @Override + public boolean blockActivated(World world, int x, int y, int z, EntityPlayer player) { + this.inverted = !this.inverted; + return true; + } + + public void updateSensor(World world, int x, int y, int z, byte redstone) { + int direction = SimpleTech.getDirectionFromMetadata(world.getBlockMetadata(x, y, z)); + + // Recreates metadata using the redstone signal and the block direction values. + world.setBlockMetadataWithNotify(x, y, z, SimpleTech.createMetadata(direction, redstone)); + + // Updates block's neighbors. + world.notifyBlocksOfNeighborChange(x, y, z, this.id); + world.notifyBlocksOfNeighborChange(x, y - 1, z, this.id); + + world.markBlocksDirty(x, y, z, x, y, z); + } +} diff --git a/src/main/java/turniplabs/simpletech/block/BlockTrappedChest.java b/src/main/java/turniplabs/simpletech/block/BlockTrappedChest.java @@ -0,0 +1,105 @@ +package turniplabs.simpletech.block; + +import net.minecraft.core.block.BlockChest; +import net.minecraft.core.block.material.Material; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.sound.SoundType; +import net.minecraft.core.world.World; +import net.minecraft.core.world.WorldSource; +import turniplabs.simpletech.SimpleTech; + +import java.util.Random; + +public class BlockTrappedChest extends BlockChest { + public BlockTrappedChest(String key, int id, Material material) { + super(key, id, material); + this.withTexCoords(9, 1, 9, 1, 11, 1, 10, 1, 10, + 1, 10, 1); + this.setTickOnLoad(true); + } + + @Override + public int tickRate() { + return 20; + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean canProvidePower() { + return true; + } + + @Override + public boolean renderAsNormalBlock() { + return false; + } + + @Override + public boolean isPoweringTo(WorldSource blockAccess, int x, int y, int z, int side) { + // Debug code to display metadata. + boolean debug = false; + if (debug) { + System.out.println("METADATA: " + Integer.toString( + blockAccess.getBlockMetadata(x, y, z), 2)); + System.out.println("DIRECTION: " + Integer.toString( + SimpleTech.getDirectionFromMetadata(blockAccess.getBlockMetadata(x, y, z)), 2)); + System.out.println("REDSTONE: " + Integer.toString(SimpleTech.getRedstoneFromMetadata( + blockAccess.getBlockMetadata(x, y, z)), 2)); + System.out.println("METADATA (recombined): " + Integer.toString(SimpleTech.createMetadata( + SimpleTech.getDirectionFromMetadata(blockAccess.getBlockMetadata(x, y, z)), + SimpleTech.getRedstoneFromMetadata(blockAccess.getBlockMetadata(x, y, z))), 2)); + } + + return SimpleTech.getRedstoneFromMetadata(blockAccess.getBlockMetadata(x, y, z)) > 0; + } + + @Override + public void onBlockRemoval(World world, int x, int y, int z) { + if (SimpleTech.getRedstoneFromMetadata(world.getBlockMetadata(x, y, z)) > 0) { + this.notifyNeighbors(world, x, y, z); + } + + super.onBlockRemoval(world, x, y, z); + } + + @Override + public boolean blockActivated(World world, int x, int y, int z, EntityPlayer player) { + this.setState(world, x, y, z, (byte) 1); + + world.scheduleBlockUpdate(x, y, z, this.id, this.tickRate()); + world.playSoundEffect(SoundType.GUI_SOUNDS,x + 0.5, y + 0.5, z + 0.5, + "random.click", 0.3f, 0.6f); + + return super.blockActivated(world, x, y, z, player); + } + + @Override + public void updateTick(World world, int x, int y, int z, Random rand) { + if (!world.isClientSide) { + if (SimpleTech.getRedstoneFromMetadata(world.getBlockMetadata(x, y, z)) > 0) { + this.setState(world, x, y, z, (byte) 0); + } + } + } + + private void setState(World world, int x, int y, int z, byte redstone) { + int direction = SimpleTech.getDirectionFromMetadata(world.getBlockMetadata(x, y, z)); + + // Recreates metadata using the redstone signal and the block direction values. + world.setBlockMetadataWithNotify(x, y, z, SimpleTech.createMetadata(direction, redstone)); + + // Updates block's neighbors. + this.notifyNeighbors(world, x, y, z); + + world.markBlocksDirty(x, y, z, x, y, z); + } + + private void notifyNeighbors(World world, int x, int y, int z) { + world.notifyBlocksOfNeighborChange(x, y, z, this.id); + world.notifyBlocksOfNeighborChange(x, y - 1, z, this.id); + } +} diff --git a/src/main/java/turniplabs/simpletech/block/entity/TileEntityAllocator.java b/src/main/java/turniplabs/simpletech/block/entity/TileEntityAllocator.java @@ -0,0 +1,99 @@ +package turniplabs.simpletech.block.entity; + +import com.mojang.nbt.CompoundTag; +import com.mojang.nbt.ListTag; +import net.minecraft.core.block.entity.TileEntity; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.player.inventory.IInventory; + +public class TileEntityAllocator extends TileEntity implements IInventory { + private ItemStack allocatorFilterItem; + + @Override + public int getSizeInventory() { + return 1; + } + + @Override + public ItemStack getStackInSlot(int i) { + return i == 0 ? this.allocatorFilterItem : null; + } + + @Override + public ItemStack decrStackSize(int i, int j) { + if (i != 0) { + return null; + } else if (this.allocatorFilterItem != null) { + ItemStack itemstack; + if (this.allocatorFilterItem.stackSize <= j) { + itemstack = this.allocatorFilterItem; + this.allocatorFilterItem = null; + return itemstack; + } else { + itemstack = this.allocatorFilterItem.splitStack(j); + if (this.allocatorFilterItem.stackSize == 0) { + this.allocatorFilterItem = null; + } + + return itemstack; + } + } else { + return null; + } + } + + @Override + public void setInventorySlotContents(int i, ItemStack itemStack) { + if (i == 0) { + this.allocatorFilterItem = itemStack; + if (itemStack != null && itemStack.stackSize > this.getInventoryStackLimit()) { + itemStack.stackSize = this.getInventoryStackLimit(); + } + } + } + + @Override + public String getInvName() { + return "Allocator"; + } + + @Override + public int getInventoryStackLimit() { + return 1; + } + + @Override + public boolean canInteractWith(EntityPlayer entityPlayer) { + return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) == this && + entityPlayer.distanceToSqr((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D, + (double) this.zCoord + 0.5D) <= 64.0D; + } + + @Override + public void readFromNBT(CompoundTag nbttagcompound) { + super.readFromNBT(nbttagcompound); + ListTag items = nbttagcompound.getList("Items"); + if (items.tagCount() != 0) { + CompoundTag item = (CompoundTag)items.tagAt(0); + int slot = item.getByte("Slot") & 255; + if(slot == 0) { + this.allocatorFilterItem = ItemStack.readItemStackFromNbt(item); + } + } + } + + @Override + public void writeToNBT(CompoundTag nbttagcompound) { + super.writeToNBT(nbttagcompound); + ListTag items = new ListTag(); + if (this.allocatorFilterItem != null) { + CompoundTag item = new CompoundTag(); + item.putByte("Slot", (byte)0); + this.allocatorFilterItem.writeToNBT(item); + items.addTag(item); + } + + nbttagcompound.put("Items", items); + } +} diff --git a/src/main/java/turniplabs/simpletech/block/entity/TileEntityFan.java b/src/main/java/turniplabs/simpletech/block/entity/TileEntityFan.java @@ -0,0 +1,96 @@ +package turniplabs.simpletech.block.entity; + +import net.minecraft.core.block.entity.TileEntity; +import net.minecraft.core.entity.Entity; +import net.minecraft.core.entity.EntityItem; +import net.minecraft.core.util.phys.AABB; +import net.minecraft.core.world.World; +import turniplabs.simpletech.SimpleTech; + +import java.util.List; + +public class TileEntityFan extends TileEntity { + private final int range; + + public TileEntityFan(int range) { + this.range = range; + } + + public TileEntityFan() { + // Always define the default constructor when working with tile entities. + this(SimpleTech.FAN_RANGE); + } + + @Override + public void updateEntity() { + if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord) || + worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord + 1, zCoord)) { + this.blow(worldObj, xCoord, yCoord, zCoord); + } + } + + private void blow(World world, int x, int y, int z) { + int dx = -SimpleTech.getDirectionX(world, x, y, z); + int dy = -SimpleTech.getDirectionY(world, x, y, z); + int dz = -SimpleTech.getDirectionZ(world, x, y, z); + + int px = x; + int py = y; + int pz = z; + + for (int i = 0; i < this.range; ++i) { + px += dx; + py += dy; + pz += dz; + + if (world.isBlockOpaqueCube(px, py, pz)) { + break; + } + + List<Entity> entities = world.getEntitiesWithinAABB(Entity.class, AABB.getBoundingBoxFromPool( + px, py, pz, px + 1, py + 1, pz + 1) + ); + + for (Entity entity : entities) { + if (entity instanceof EntityItem) { + this.pushEntity(entity, dx, dy, dz); + } + } + } + } + + private void pushEntity(Entity entity, int dx, int dy, int dz) { + double maxspeed = 0.4; + double boost = 0.1; + + if (Math.abs(dx) != 0) { + if (entity.xd * (double) dx < 0.0) { + entity.xd = 0.0; + } + + if (entity.xd * (double) dx <= maxspeed) { + entity.xd += (double) dx * boost; + } + } else if (Math.abs(dy) != 0) { + if (entity.yd * (double) dy < 0.0) { + entity.yd = 0.0; + } + + if (dy > 0) { + boost *= 0.5; + } + + if (entity.yd * (double) dy <= maxspeed) { + entity.yd += (double) dy * boost; + } + } else if (Math.abs(dz) != 0) { + if (entity.zd * (double) dz < 0.0) { + entity.zd = 0.0; + } + + if (entity.zd * (double) dz <= maxspeed) { + entity.zd += (double) dz * boost; + } + } + } +} diff --git a/src/main/java/turniplabs/simpletech/block/entity/TileEntityLightSensor.java b/src/main/java/turniplabs/simpletech/block/entity/TileEntityLightSensor.java @@ -0,0 +1,29 @@ +package turniplabs.simpletech.block.entity; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.entity.TileEntity; +import turniplabs.simpletech.block.BlockLightSensor; + +public class TileEntityLightSensor extends TileEntity { + @Override + public void updateEntity() { + // If the world object if valid... + if (this.worldObj != null && !this.worldObj.isClientSide) { + Block block = this.getBlockType(); + // If it's a light sensor... + if (block instanceof BlockLightSensor) { + BlockLightSensor lightSensor = ((BlockLightSensor) block); + byte redstone; + if (lightSensor.isInverted()) { + redstone = (byte) (this.worldObj.isDaytime() ? 1 : 0); // Daytime mode. + } else { + redstone = (byte) (this.worldObj.isDaytime() ? 0 : 1); // Nighttime mode. + } + + // Sends redstone value. + lightSensor.updateSensor(this.worldObj, this.xCoord, this.yCoord, + this.zCoord, redstone); + } + } + } +} diff --git a/src/main/java/turniplabs/simpletech/gui/GuiAllocator.java b/src/main/java/turniplabs/simpletech/gui/GuiAllocator.java @@ -0,0 +1,36 @@ +package turniplabs.simpletech.gui; + +import net.minecraft.client.gui.GuiContainer; +import net.minecraft.core.player.inventory.InventoryPlayer; +import org.lwjgl.opengl.GL11; +import turniplabs.simpletech.block.entity.TileEntityAllocator; +import turniplabs.simpletech.player.inventory.ContainerAllocator; + +public class GuiAllocator extends GuiContainer { + private TileEntityAllocator allocatorInv; + + public GuiAllocator(InventoryPlayer playerInventory, TileEntityAllocator allocator) { + super(new ContainerAllocator(playerInventory, allocator)); + this.allocatorInv = allocator; + } + + @Override + protected void drawGuiContainerForegroundLayer() { + this.fontRenderer.drawString("Allocator", 60, 6, 4210752); + this.fontRenderer.drawString("Inventory", 8, this.ySize - 96 + 2, 4210752); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float f) { + int i = this.mc.renderEngine.getTexture("/assets/simpletech/gui/allocator.png"); + + GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + this.mc.renderEngine.bindTexture(i); + + int j = (this.width - this.xSize) / 2; + int k = (this.height - this.ySize) / 2; + + this.drawTexturedModalRect(j, k, 0, 0, this.xSize, this.ySize); + } +} diff --git a/src/main/java/turniplabs/simpletech/mixin/MinecraftMixin.java b/src/main/java/turniplabs/simpletech/mixin/MinecraftMixin.java @@ -0,0 +1,20 @@ +package turniplabs.simpletech.mixin; + +import net.minecraft.client.Minecraft; +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.CallbackInfoReturnable; + +@Mixin(value = Minecraft.class, remap = false) +final class MinecraftMixin { + @Shadow + private static Minecraft theMinecraft; + + @Inject(method = "getMinecraft(Ljava/lang/Class;)Lnet/minecraft/client/Minecraft;", at = @At("HEAD"), + require = 0, cancellable = true) + private static void removeGetterLimitation(Class<?> caller, CallbackInfoReturnable<Minecraft> cir) { + cir.setReturnValue(theMinecraft); + } +} diff --git a/src/main/java/turniplabs/simpletech/mixin/RenderBlocksMixin.java b/src/main/java/turniplabs/simpletech/mixin/RenderBlocksMixin.java @@ -0,0 +1,49 @@ +package turniplabs.simpletech.mixin; + +import net.minecraft.client.render.RenderBlocks; +import net.minecraft.core.block.Block; +import net.minecraft.core.util.helper.Side; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import turniplabs.simpletech.block.BlockAllocator; +import turniplabs.simpletech.block.BlockFan; + +@Mixin(value = RenderBlocks.class, remap = false) +final class RenderBlocksMixin { + @Redirect(method = "renderBlockOnInventory", at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/block/Block;getBlockTextureFromSideAndMetadata(Lnet/minecraft/core/util/helper/Side;I)I"), + require = 0) + private int changeBlockInventoryRender(Block block, Side side, int meta) { + if (block instanceof BlockFan) { + if (side == Side.SOUTH) { + return block.getBlockTextureFromSideAndMetadata(Side.BOTTOM, meta); + } + + if (side == Side.BOTTOM) { + return block.getBlockTextureFromSideAndMetadata(Side.TOP, meta); + } + } + + if (block instanceof BlockAllocator) { + BlockAllocator allocator = ((BlockAllocator) block); + if (side == Side.TOP) { + return Block.texCoordToIndex(allocator.getTop()[0], allocator.getTop()[1]); + } + + if (side == Side.BOTTOM) { + return Block.texCoordToIndex(allocator.getTop()[0], allocator.getTop()[1]); + } + + if (side == Side.SOUTH) { + return Block.texCoordToIndex(allocator.getFront()[0], allocator.getFront()[1]); + } + + if (side == Side.NORTH) { + return Block.texCoordToIndex(allocator.getBack()[0], allocator.getBack()[1]); + } + } + + return block.getBlockTextureFromSideAndMetadata(side, meta); + } +} diff --git a/src/main/java/turniplabs/simpletech/player/inventory/ContainerAllocator.java b/src/main/java/turniplabs/simpletech/player/inventory/ContainerAllocator.java @@ -0,0 +1,47 @@ +package turniplabs.simpletech.player.inventory; + +import net.minecraft.core.InventoryAction; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.player.inventory.Container; +import net.minecraft.core.player.inventory.IInventory; +import net.minecraft.core.player.inventory.slot.Slot; +import turniplabs.simpletech.block.entity.TileEntityAllocator; + +import java.util.List; + +public class ContainerAllocator extends Container { + private final TileEntityAllocator allocator; + + public ContainerAllocator(IInventory playerInventory, TileEntityAllocator allocator) { + this.allocator = allocator; + + // Adding allocator slot. + this.addSlot(new Slot(allocator, 0, 80, 36)); + + // Adding player inventory slots. + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 9; ++j) { + this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); + } + } + + for(int i = 0; i < 9; ++i) { + this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } + } + + @Override + public boolean isUsableByPlayer(EntityPlayer entityPlayer) { + return this.allocator.canInteractWith(entityPlayer); + } + + @Override + public List<Integer> getMoveSlots(InventoryAction inventoryAction, Slot slot, int i, EntityPlayer entityPlayer) { + return null; + } + + @Override + public List<Integer> getTargetSlots(InventoryAction inventoryAction, Slot slot, int i, EntityPlayer entityPlayer) { + return null; + } +} diff --git a/src/main/resources/assets/simpletech/block/allocator_back.png b/src/main/resources/assets/simpletech/block/allocator_back.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/allocator_back_top_bottom.png b/src/main/resources/assets/simpletech/block/allocator_back_top_bottom.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/allocator_front.png b/src/main/resources/assets/simpletech/block/allocator_front.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/allocator_front_top_bottom.png b/src/main/resources/assets/simpletech/block/allocator_front_top_bottom.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/fan_front.png b/src/main/resources/assets/simpletech/block/fan_front.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/fan_front_powered.png b/src/main/resources/assets/simpletech/block/fan_front_powered.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/jump_pad.png b/src/main/resources/assets/simpletech/block/jump_pad.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/light_sensor.png b/src/main/resources/assets/simpletech/block/light_sensor.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/misc_side.png b/src/main/resources/assets/simpletech/block/misc_side.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/block/misc_top_bottom.png b/src/main/resources/assets/simpletech/block/misc_top_bottom.png Binary files differ. diff --git a/src/main/resources/assets/simpletech/gui/allocator.png b/src/main/resources/assets/simpletech/gui/allocator.png Binary files differ. diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json @@ -0,0 +1,30 @@ +{ + "schemaVersion": 1, + "id": "simpletech", + "version": "${version}", + "name": "Simple Tech", + "description": "Adds simple blocks to automate stuff", + "authors": [ + "Ambos" + ], + "contact": { + "homepage": "https://github.com/Turnip-Labs", + "sources": "https://github.com/Turnip-Labs/simple-tech", + "issues": "https://github.com/Turnip-Labs/simple-tech/issues" + }, + "license": "CC-BY-NC-SA-3.0", + "environment": "*", + "entrypoints": { + "main": [ + "turniplabs.simpletech.SimpleTech" + ] + }, + "mixins": [ + "simpletech.mixins.json" + ], + "depends": { + "fabricloader": ">=0.13.3" + }, + "suggests": { + } +} diff --git a/src/main/resources/lang/simpletech/en_US.lang b/src/main/resources/lang/simpletech/en_US.lang @@ -0,0 +1,12 @@ +tile.block.fan.unpowered.name=Fan +tile.block.fan.unpowered.desc=Fan goes whoosh! +tile.block.fan.powered.name=Powered Fan +tile.block.fan.powered.desc=Fan goes whoosh! +tile.block.jumppad.name=Jump Pad +tile.block.jumppad.desc=Boing! Hop hop! +tile.chest.trapped.name=Trapped Chest +tile.chest.trapped.desc=It's a trap! +tile.block.lightsensor.name=Light Sensor +tile.block.lightsensor.desc=...and there was light +tile.block.allocator.name=Allocator +tile.block.allocator.desc= +\ No newline at end of file diff --git a/src/main/resources/lang/simpletech/fr_FR.lang b/src/main/resources/lang/simpletech/fr_FR.lang @@ -0,0 +1,12 @@ +tile.block.fan.unpowered.name=Ventilateur +tile.block.fan.unpowered.desc= +tile.block.fan.powered.name=Ventilateur en marche +tile.block.fan.powered.desc= +tile.block.jumppad.name=Trampoline +tile.block.jumppad.desc=Boing ! +tile.chest.trapped.name=Coffre piégé +tile.chest.trapped.desc=J'active ma carte piège ! +tile.block.lightsensor.name=Détecteur de lumière +tile.block.lightsensor.desc=... et la lumière fut +tile.block.allocator.name=Allocateur +tile.block.allocator.desc= +\ No newline at end of file diff --git a/src/main/resources/simpletech.mixins.json b/src/main/resources/simpletech.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "turniplabs.simpletech.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MinecraftMixin", + "RenderBlocksMixin" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +}