Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f0bfbfec48 | |||
| 06a8843a65 | |||
| 2bca23d75d | |||
| b47543d166 | |||
| a340925d98 | |||
| b8e53adf40 | |||
| 44544c598f | |||
| 0be7322c2c | |||
| a521e827db | |||
| bcee2ec427 | |||
| 17648633fe | |||
| fcbebd4ffc | |||
| 9e41d543f5 | |||
| 81cc0b804d | |||
| e1fc9908b3 | |||
| 9ed1535477 | |||
| 1ef345d4a4 | |||
| ff7d1b9719 | |||
| 88c9370e4f | |||
| f2aae3ef0f | |||
| 12739f1e66 | |||
| 81d2170ada | |||
| 0f469e9df6 | |||
| 0f34f09b32 | |||
| 8e54a8fed9 | |||
| ca007a3737 | |||
| 92b6650022 | |||
| e1cd3bba25 | |||
| 689bf6e8d9 | |||
| c8a5049d71 | |||
| 10a1a6d855 | |||
| d9bb81a00f | |||
| 39e038d916 | |||
| 575a625f75 | |||
| 89ea923c43 | |||
| 5d818eb03e | |||
| 12ca8d109a | |||
| e34126458b | |||
| 0ac918c363 | |||
| b6160e40bc | |||
| cf103b06c1 | |||
| f0d0595c8f | |||
| b756d68be1 | |||
| 60b07e5ca5 | |||
| 7c99fca789 | |||
| ab393b0ed1 | |||
| 957bc4c5cc | |||
| 133ed1f09d | |||
| e90dd2f9c6 | |||
| 9719c7ffc3 | |||
| 319d92a371 | |||
| db9ec2b070 | |||
| 5d33005aaf | |||
| 87cf070b33 | |||
| 3a0552c56e | |||
| b1a55f3a79 | |||
| 226e9596ee | |||
| 5cab9c8799 | |||
| 1d2ac29742 | |||
| cbe6012b98 | |||
| 8a0dd192e5 | |||
| 1842febf86 | |||
| a97b35f3d0 | |||
| 00d4c20d9f | |||
| d2b69671f5 | |||
| 1394ab0863 | |||
| 5efc085693 | |||
| 359e3f7e63 | |||
| fa3e41e687 | |||
| 4e86c92720 | |||
| 159f4c7f14 | |||
| aff94cec8c | |||
| 07dfa3db2e | |||
| e0e139900f | |||
| 9942f2d32c | |||
| 858826d1fa | |||
| 90ad345672 | |||
| 9a81ebfa50 | |||
| da9fa3d697 | |||
| ee7fe9f40d | |||
| 2184d03d0b | |||
| cae1621613 | |||
| e8574d03ea | |||
| d28f33d198 | |||
| 7df5bf4076 | |||
| 66760865a3 | |||
| e4a08ba99d | |||
| f11e9e2a4c | |||
| 7a469c1a1d | |||
| e256a4f664 | |||
| 73cc3f8998 | |||
| 9c9a49f9e7 | |||
| 44c0931c02 | |||
| 874f46ed4d | |||
| b7949e4134 | |||
| ea95913ec8 | |||
| 423ab81813 | |||
| d82c713112 | |||
| 45cbc40177 | |||
| 33d7f02323 | |||
| 4e42b17e81 | |||
| 0e7e9313ee | |||
| 2bba843313 | |||
| a0949297d5 | |||
| 420fb272b4 | |||
| debd2de42e | |||
| 3fb813a81b | |||
| ab05f5fec9 | |||
| 9e4f51db6e | |||
| b8d4f0cffa | |||
| fc0f8eab56 | |||
| 74480502b1 | |||
| 7e1bfdb5ac | |||
| 41b7900706 | |||
| 1f9707e256 | |||
| 7656157b0d | |||
| 954ce1442e | |||
| 739277ab64 | |||
| cf656e1540 | |||
| ab6f46077b | |||
| e9c7312e98 | |||
| 006cf2f8c1 | |||
| 636dce66e3 | |||
| 2787796cd3 | |||
| ee67c5ea50 |
@@ -21,7 +21,9 @@ jobs:
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
|
||||
- name: Build with Gradle
|
||||
- name: Generate Resources
|
||||
run: ./gradlew generateData
|
||||
- name: Build
|
||||
run: ./gradlew build
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
|
||||
@@ -23,10 +23,14 @@ jobs:
|
||||
run: chmod +x gradlew
|
||||
- name: Validate no assets
|
||||
run: test ! -d ./src/generated
|
||||
- name: Generate resources
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew generateData
|
||||
- name: Build with Gradle
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew generateData build
|
||||
run: ./gradlew build
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
@@ -34,8 +38,19 @@ jobs:
|
||||
path: build/libs/
|
||||
- name: Publish to github packages
|
||||
env:
|
||||
KEY_STORE_PASS: ${{ secrets.KEY_STORE_PASS }}
|
||||
KEY_STORE_ALIAS: ${{ secrets.KEY_STORE_ALIAS }}
|
||||
KEY_STORE_KEY_PASS: ${{ secrets.KEY_STORE_KEY_PASS }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew publish
|
||||
run: ./gradlew publishMavenPublicationToGitHubPackagesRepository --no-daemon --max-workers 1
|
||||
- name: Publish to modmaven
|
||||
env:
|
||||
KEY_STORE_PASS: ${{ secrets.KEY_STORE_PASS }}
|
||||
KEY_STORE_ALIAS: ${{ secrets.KEY_STORE_ALIAS }}
|
||||
KEY_STORE_KEY_PASS: ${{ secrets.KEY_STORE_KEY_PASS }}
|
||||
MODMAVEN_USER: ${{ secrets.MODMAVEN_USER }}
|
||||
MODMAVEN_PASSWORD: ${{ secrets.MODMAVEN_PASSWORD }}
|
||||
run: ./gradlew publishMavenPublicationToModmavenRepository --no-daemon --max-workers 1
|
||||
- name: Upload to curseforge
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -72,19 +72,41 @@ The API for Applied Energistics 2. It is open source to discuss changes, improve
|
||||
|
||||
### Maven
|
||||
|
||||
We use Github Packages as maven repository now. You can use the following snippet as example on how to add a repository to your gradle build file.
|
||||
Our authoritative Maven repository is Github Packages, which you can also use in your builds. Use of Github Packages
|
||||
[requires special setup](https://docs.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-gradle-for-use-with-github-packages#authenticating-to-github-packages)
|
||||
to authenticate with your personal access token.
|
||||
|
||||
AE2 is also available without authentication from Modmaven.
|
||||
|
||||
You can use the following snippet as example on how to add a repository to your gradle build file.
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name "AE2"
|
||||
url "https://maven.pkg.github.com/AppliedEnergistics/Applied-Energistics-2"
|
||||
name "Modmaven"
|
||||
url "https://modmaven.k-4u.nl/"
|
||||
// For Gradle 5.1 and above, limit it to just AE2
|
||||
content {
|
||||
includeGroup 'appeng'
|
||||
}
|
||||
}
|
||||
|
||||
// Required for libblockattributes
|
||||
maven {
|
||||
name = "BuildCraft"
|
||||
url = "https://mod-buildcraft.com/maven"
|
||||
content {
|
||||
includeGroup "alexiil.mc.lib"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
When compiling against the AE2 API you can use gradle dependencies, just add
|
||||
|
||||
dependencies {
|
||||
compileOnly "appeng:appliedenergistics2:VERSION:api"
|
||||
modCompileOnly "appeng:appliedenergistics2-fabric:VERSION:api"
|
||||
|
||||
// Include only if you want AE2 at runtime
|
||||
modRuntimeOnly "appeng:appliedenergistics2-fabric:VERSION"
|
||||
}
|
||||
|
||||
or add the `compileOnly` line to your existing dependencies task to your build.gradle.
|
||||
|
||||
+28
-14
@@ -34,6 +34,9 @@ repositories {
|
||||
maven {
|
||||
name = "BuildCraft"
|
||||
url = "https://mod-buildcraft.com/maven"
|
||||
content {
|
||||
includeGroup "alexiil.mc.lib"
|
||||
}
|
||||
}
|
||||
maven {
|
||||
name = "HYWLA"
|
||||
@@ -42,10 +45,6 @@ repositories {
|
||||
includeGroup "mcp.mobius.waila"
|
||||
}
|
||||
}
|
||||
maven {
|
||||
name = 'Earthcomputer Mods'
|
||||
url = 'https://dl.bintray.com/earthcomputer/mods'
|
||||
}
|
||||
}
|
||||
|
||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
|
||||
@@ -141,13 +140,20 @@ dependencies {
|
||||
include "alexiil.mc.lib:libblockattributes-items:${libblockattributes_version}"
|
||||
include "alexiil.mc.lib:libblockattributes-fluids:${libblockattributes_version}"
|
||||
|
||||
modCompileOnly("me.shedaniel:RoughlyEnoughItems:5.0.2-unstable") {
|
||||
// Energy API
|
||||
modApi "teamreborn:energy:${tr_energy_version}"
|
||||
include "teamreborn:energy:${tr_energy_version}"
|
||||
|
||||
modCompileOnly("me.shedaniel:RoughlyEnoughItems:${rei_version}") {
|
||||
exclude group: "net.fabricmc.fabric-api"
|
||||
}
|
||||
modCompileOnly("mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75") {
|
||||
exclude group: "net.fabricmc.fabric-api"
|
||||
}
|
||||
modRuntime("me.shedaniel:RoughlyEnoughItems:5.0.2-unstable") {
|
||||
modRuntime("me.shedaniel:RoughlyEnoughItems:${rei_version}") {
|
||||
exclude group: "net.fabricmc.fabric-api"
|
||||
}
|
||||
modRuntime("TechReborn:TechReborn-1.16:3.5.1+build.101") {
|
||||
exclude group: "net.fabricmc.fabric-api"
|
||||
}
|
||||
// modRuntimeOnly "mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75"
|
||||
@@ -174,11 +180,14 @@ processResources {
|
||||
apply from: 'gradle/scripts/artifacts.gradle'
|
||||
apply from: 'gradle/scripts/curseforge.gradle'
|
||||
|
||||
if (!version.endsWith("-SNAPSHOT")) {
|
||||
publishing {
|
||||
// configure the maven publication
|
||||
publishing {
|
||||
if (!version.endsWith("-SNAPSHOT")) {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
maven(MavenPublication) {
|
||||
groupId = project.group
|
||||
artifactId = 'appliedenergistics2-fabric'
|
||||
version = project.version
|
||||
|
||||
// add all the jars that should be included when publishing to maven
|
||||
artifact(remapJar) {
|
||||
@@ -187,14 +196,11 @@ if (!version.endsWith("-SNAPSHOT")) {
|
||||
artifact(sourcesJar) {
|
||||
builtBy remapSourcesJar
|
||||
}
|
||||
artifact javadocJar
|
||||
artifact apiJar
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// configure the maven publication
|
||||
publishing {
|
||||
// select the repositories you want to publish to
|
||||
repositories {
|
||||
maven {
|
||||
credentials {
|
||||
@@ -204,6 +210,14 @@ publishing {
|
||||
name = "GitHubPackages"
|
||||
url = "https://maven.pkg.github.com/AppliedEnergistics/Applied-Energistics-2"
|
||||
}
|
||||
maven {
|
||||
credentials {
|
||||
username System.getenv("MODMAVEN_USER")
|
||||
password System.getenv("MODMAVEN_PASSWORD")
|
||||
}
|
||||
name = "modmaven"
|
||||
url = "https://modmaven.k-4u.nl/artifactory/local-releases/"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-10
@@ -11,27 +11,23 @@ org.gradle.jvmargs=-Xmx2G
|
||||
|
||||
minecraft_version=1.16.2
|
||||
yarn_mappings=1.16.2+build.6
|
||||
loader_version=0.9.1+build.205
|
||||
loader_version=0.9.2+build.206
|
||||
|
||||
#Fabric api
|
||||
fabric_version=0.17.2+build.396-1.16
|
||||
fabric_version=0.20.1+build.401-1.16
|
||||
|
||||
loom_version=0.4-SNAPSHOT
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 1.0.0
|
||||
maven_group = net.fabricmc
|
||||
archives_base_name = fabric-example-mod
|
||||
|
||||
# Kotlin
|
||||
kotlin_version=1.3.61
|
||||
fabric_kotlin_version=1.3.61+build.1
|
||||
|
||||
libblockattributes_version=0.7.1-pre.9
|
||||
# Dependencies
|
||||
libblockattributes_version=0.8.0
|
||||
tr_energy_version=0.1.0
|
||||
rei_version=5.2.10
|
||||
|
||||
#########################################################
|
||||
# Deployment #
|
||||
#########################################################
|
||||
website_version=1.16.1
|
||||
curse_versions=1.16.1
|
||||
curseforge_project=223794
|
||||
|
||||
@@ -33,8 +33,8 @@ dependencies {
|
||||
compileOnly "mcjty.theoneprobe:TheOneProbe-${minecraft_release}:${minecraft_release}-${top_version}:api"
|
||||
|
||||
// Runtime, Mods
|
||||
// FIXME 1.16.2 runtimeOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}:${jei_version}")
|
||||
// FIXME 1.16.2 runtimeOnly fg.deobf("mcjty.theoneprobe:TheOneProbe-${minecraft_release}:${minecraft_release}-${top_version}")
|
||||
runtimeOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}:${jei_version}")
|
||||
runtimeOnly fg.deobf("mcjty.theoneprobe:TheOneProbe-${minecraft_release}:${minecraft_release}-${top_version}")
|
||||
//runtimeOnly fg.deobf("team.chisel.ctm:CTM:${ctm_version}")
|
||||
|
||||
// unit test dependencies
|
||||
|
||||
@@ -27,21 +27,27 @@ import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
|
||||
public enum PowerUnits {
|
||||
AE("gui.appliedenergistics2.units.appliedenergstics"), // Native Units - AE Energy
|
||||
EU("gui.appliedenergistics2.units.ic2"), // IndustrialCraft 2 - Energy Units
|
||||
RF("gui.appliedenergistics2.units.rf"); // RF - Redstone Flux
|
||||
AE("gui.appliedenergistics2.units.appliedenergstics", "AE"), // Native Units - AE Energy
|
||||
EU("gui.appliedenergistics2.units.ic2", "EU"), // IndustrialCraft 2 - Energy Units
|
||||
TR("gui.appliedenergistics2.units.tr", "E"); // TR - TechReborn energy
|
||||
|
||||
/**
|
||||
* unlocalized name for the power unit.
|
||||
*/
|
||||
public final String unlocalizedName;
|
||||
|
||||
/**
|
||||
* unlocalized name for the power unit's symbol used to display values.
|
||||
*/
|
||||
public final String symbolName;
|
||||
/**
|
||||
* please do not edit this value, it is set when AE loads its config files.
|
||||
*/
|
||||
public double conversionRatio = 1.0;
|
||||
|
||||
PowerUnits(final String un) {
|
||||
PowerUnits(final String un, String symbolName) {
|
||||
this.unlocalizedName = un;
|
||||
this.symbolName = symbolName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,4 +70,8 @@ public enum PowerUnits {
|
||||
return new TranslatableText(unlocalizedName);
|
||||
}
|
||||
|
||||
public String getSymbolName() {
|
||||
return symbolName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public enum Settings {
|
||||
|
||||
CONDENSER_OUTPUT(EnumSet.allOf(CondenserOutput.class)),
|
||||
|
||||
POWER_UNITS(EnumSet.allOf(PowerUnits.class)),
|
||||
POWER_UNITS(EnumSet.of(PowerUnits.AE, PowerUnits.TR)),
|
||||
|
||||
ACCESS(EnumSet.of(AccessRestriction.READ_WRITE, AccessRestriction.READ, AccessRestriction.WRITE)),
|
||||
|
||||
|
||||
@@ -25,12 +25,8 @@ package appeng.api.config;
|
||||
|
||||
public enum TunnelType {
|
||||
ME, // Network Tunnel
|
||||
IC2_POWER, // EU Tunnel
|
||||
FE_POWER, // Forge Energy tunnel
|
||||
REDSTONE, // Redstone Tunnel
|
||||
FLUID, // Fluid Tunnel
|
||||
ITEM, // Item Tunnel
|
||||
LIGHT, // Light Tunnel
|
||||
BUNDLED_REDSTONE, // Bundled Redstone Tunnel
|
||||
COMPUTER_MESSAGE // Computer Message Tunnel
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ public interface ICraftingHelper {
|
||||
* @param stack If null, a new item will be created to hold the encoded pattern.
|
||||
* Otherwise the given item must already contains an encoded
|
||||
* pattern that will be overwritten.
|
||||
* @throws IllegalArgumentException If either in or out contain only empty
|
||||
* ItemStacks.
|
||||
* @return A new encoded pattern, or the given stack with the pattern encoded in
|
||||
* it.
|
||||
*/
|
||||
@@ -73,6 +75,8 @@ public interface ICraftingHelper {
|
||||
* operation by the ME system.
|
||||
* @param allowSubstitutes Controls whether the ME system will allow the use of
|
||||
* equivalent items to craft this recipe.
|
||||
* @throws IllegalArgumentException If either in or out contain only empty
|
||||
* ItemStacks.
|
||||
*/
|
||||
ItemStack encodeCraftingPattern(@Nullable ItemStack stack, CraftingRecipe recipe, ItemStack[] in, ItemStack out,
|
||||
boolean allowSubstitutes);
|
||||
|
||||
@@ -71,10 +71,6 @@ public interface IParts {
|
||||
|
||||
IItemDefinition p2PTunnelFluids();
|
||||
|
||||
IItemDefinition p2PTunnelEU();
|
||||
|
||||
IItemDefinition p2PTunnelFE();
|
||||
|
||||
IItemDefinition p2PTunnelLight();
|
||||
|
||||
IItemDefinition cableAnchor();
|
||||
|
||||
@@ -82,11 +82,6 @@ public interface IRegistryContainer {
|
||||
*/
|
||||
IPlayerRegistry players();
|
||||
|
||||
/**
|
||||
* get access to the world-gen api.
|
||||
*/
|
||||
IWorldGen worldgen();
|
||||
|
||||
/**
|
||||
* Register your IPart models before using them.
|
||||
*/
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013 AlgorithmX2
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package appeng.api.features;
|
||||
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public interface IWorldGen {
|
||||
|
||||
void enableWorldGenForDimension(WorldGenType type, Identifier dimID);
|
||||
|
||||
void disableWorldGenForDimension(WorldGenType type, Identifier dimID);
|
||||
|
||||
boolean isWorldGenEnabled(WorldGenType type, ServerWorld w);
|
||||
|
||||
enum WorldGenType {
|
||||
CERTUS_QUARTZ, CHARGED_CERTUS_QUARTZ, METEORITES
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,23 @@
|
||||
|
||||
package appeng.api.implementations.items;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Material;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IGrowableCrystal {
|
||||
|
||||
ItemStack triggerGrowth(ItemStack is);
|
||||
|
||||
float getMultiplier(Block blk, Material mat);
|
||||
/**
|
||||
* Gets the crystal growth multiplier based on the material it is submerged in.
|
||||
*
|
||||
* @param state The blockstate of the block the crystal is currently in.
|
||||
* @return The multiplier for the growth tick progress. Zero if the crystal
|
||||
* cannot grow in the current material.
|
||||
*/
|
||||
float getMultiplier(BlockState state, @Nullable World world, @Nullable BlockPos pos);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
|
||||
import net.minecraft.Bootstrap;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
@@ -11,16 +14,22 @@ import net.minecraft.data.DataGenerator;
|
||||
import appeng.data.providers.loot.BlockDropProvider;
|
||||
import appeng.data.providers.recipes.SlabStairRecipes;
|
||||
import appeng.data.providers.tags.ConventionTagProvider;
|
||||
import appeng.data.providers.tags.ToolTagProviders;
|
||||
|
||||
public class Entrypoint implements PreLaunchEntrypoint {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static void dump() throws Exception {
|
||||
Path output = Paths.get("../src/generated/resources");
|
||||
|
||||
LOGGER.info("Writing generated resources to {}", output.toAbsolutePath());
|
||||
|
||||
DataGenerator generator = new DataGenerator(output, Collections.emptyList());
|
||||
generator.install(new BlockDropProvider(output));
|
||||
generator.install(new SlabStairRecipes(output));
|
||||
generator.install(new ConventionTagProvider(output));
|
||||
generator.install(new ToolTagProviders(output));
|
||||
generator.run();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import appeng.core.AppEng;
|
||||
public class ConventionTagProvider extends TagProvider {
|
||||
|
||||
public ConventionTagProvider(Path outputPath) {
|
||||
super(outputPath);
|
||||
super("c", outputPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -34,6 +34,9 @@ public class ConventionTagProvider extends TagProvider {
|
||||
addItemTag("red_dyes", Items.RED_DYE);
|
||||
addItemTag("black_dyes", Items.BLACK_DYE);
|
||||
|
||||
addItemTag("certus_quartz_crystals", MATERIALS.certusQuartzCrystal(), MATERIALS.certusQuartzCrystalCharged());
|
||||
addItemTag("certus_quartz_ores", BLOCKS.quartzOre(), BLOCKS.quartzOreCharged());
|
||||
|
||||
addItemTag("iron_ingots", Items.IRON_INGOT);
|
||||
addItemTag("iron_ores", Items.IRON_ORE);
|
||||
addItemTag("gold_ingots", Items.GOLD_INGOT);
|
||||
@@ -49,6 +52,7 @@ public class ConventionTagProvider extends TagProvider {
|
||||
addItemTag("wheat_crops", Items.WHEAT);
|
||||
addItemTag("redstone_dusts", Items.REDSTONE);
|
||||
addItemTag("ender_pearls", Items.ENDER_PEARL);
|
||||
addItemTag("ender_pearl_dusts", MATERIALS.enderDust());
|
||||
addItemTag("terracotta_blocks", Items.TERRACOTTA, Items.WHITE_TERRACOTTA, Items.ORANGE_TERRACOTTA,
|
||||
Items.MAGENTA_TERRACOTTA, Items.LIGHT_BLUE_TERRACOTTA, Items.YELLOW_TERRACOTTA, Items.LIME_TERRACOTTA,
|
||||
Items.PINK_TERRACOTTA, Items.GRAY_TERRACOTTA, Items.LIGHT_GRAY_TERRACOTTA, Items.CYAN_TERRACOTTA,
|
||||
|
||||
@@ -24,15 +24,17 @@ import appeng.data.providers.IAE2DataProvider;
|
||||
public abstract class TagProvider implements IAE2DataProvider {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
protected static final String CONVENTION_NAMESPACE = "c";
|
||||
protected static final String TYPE_ITEMS = "items";
|
||||
protected static final String TYPE_BLOCKS = "blocks";
|
||||
|
||||
private final String defaultNamespace;
|
||||
|
||||
private final Path outputPath;
|
||||
|
||||
private DataCache cache;
|
||||
|
||||
protected TagProvider(Path outputPath) {
|
||||
protected TagProvider(String defaultNamespace, Path outputPath) {
|
||||
this.defaultNamespace = defaultNamespace;
|
||||
this.outputPath = outputPath;
|
||||
}
|
||||
|
||||
@@ -49,15 +51,19 @@ public abstract class TagProvider implements IAE2DataProvider {
|
||||
protected abstract void generate() throws IOException;
|
||||
|
||||
protected void addItemTag(String name, ItemConvertible... items) throws IOException {
|
||||
Identifier id = parseId(name);
|
||||
|
||||
List<String> itemIds = Arrays.stream(items).map(ItemConvertible::asItem).map(Registry.ITEM::getId)
|
||||
.map(Identifier::toString).collect(Collectors.toList());
|
||||
writeTagFile(CONVENTION_NAMESPACE, TYPE_ITEMS, name, itemIds);
|
||||
writeTagFile(id.getNamespace(), TYPE_ITEMS, id.getPath(), itemIds);
|
||||
}
|
||||
|
||||
protected void addBlockTag(String name, Block... blocks) throws IOException {
|
||||
Identifier id = parseId(name);
|
||||
|
||||
List<String> itemIds = Arrays.stream(blocks).map(Registry.BLOCK::getId).map(Identifier::toString)
|
||||
.collect(Collectors.toList());
|
||||
writeTagFile(CONVENTION_NAMESPACE, TYPE_BLOCKS, name, itemIds);
|
||||
writeTagFile(id.getNamespace(), TYPE_BLOCKS, id.getPath(), itemIds);
|
||||
}
|
||||
|
||||
protected void writeTagFile(String namespace, String tagType, String tagName, List<String> entries)
|
||||
@@ -75,7 +81,15 @@ public abstract class TagProvider implements IAE2DataProvider {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return AppEng.MOD_NAME + " Convention Tags";
|
||||
return AppEng.MOD_NAME + " Tags (" + defaultNamespace + ")";
|
||||
}
|
||||
|
||||
private Identifier parseId(String name) {
|
||||
if (name.contains(":")) {
|
||||
return new Identifier(name);
|
||||
} else {
|
||||
return new Identifier(defaultNamespace, name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package appeng.data.providers.tags;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
public class ToolTagProviders extends TagProvider {
|
||||
|
||||
public ToolTagProviders(Path outputPath) {
|
||||
super("fabric", outputPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generate() throws IOException {
|
||||
addItemTag("axes", ITEMS.netherQuartzAxe(), ITEMS.certusQuartzAxe());
|
||||
addItemTag("hoes", ITEMS.netherQuartzHoe(), ITEMS.certusQuartzHoe());
|
||||
addItemTag("pickaxes", ITEMS.netherQuartzPick(), ITEMS.certusQuartzPick());
|
||||
addItemTag("shovels", ITEMS.netherQuartzShovel(), ITEMS.certusQuartzShovel());
|
||||
addItemTag("swords", ITEMS.netherQuartzSword(), ITEMS.certusQuartzSword());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return AppEng.MOD_NAME + " Tool Tags";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public final class MEAttributes {
|
||||
return null;
|
||||
}
|
||||
|
||||
return attribute.getFirstOrNull(world, be.getPos().offset(side), SearchOptions.inDirection(side.getOpposite()));
|
||||
return attribute.getFirstOrNull(world, be.getPos(), SearchOptions.inDirection(side.getOpposite()));
|
||||
}
|
||||
|
||||
// Convenience function to get an attribute of the block that is in front of a
|
||||
|
||||
@@ -232,7 +232,7 @@ public abstract class AEBaseTileBlock<T extends AEBaseBlockEntity> extends AEBas
|
||||
Platform.spawnDrops(world, pos, itemsToDrop);
|
||||
}
|
||||
|
||||
return ActionResult.FAIL;
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
if (heldItem.getItem() instanceof IMemoryCard && !(this instanceof CableBusBlock)) {
|
||||
|
||||
@@ -161,4 +161,9 @@ public class CrankBlock extends AEBaseTileBlock<CrankBlockEntity> {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasCustomRotation() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.IntProperty;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.Hand;
|
||||
@@ -80,8 +82,12 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
|
||||
|
||||
private static final ICableBusContainer NULL_CABLE_BUS = new NullCableBusContainer();
|
||||
|
||||
private static final IntProperty LIGHT_LEVEL = IntProperty.of("light_level", 0, 15);
|
||||
|
||||
public CableBusBlock() {
|
||||
super(defaultProps(AEMaterials.GLASS).nonOpaque().dropsNothing().dynamicBounds());
|
||||
super(defaultProps(AEMaterials.GLASS).nonOpaque().dropsNothing().dynamicBounds()
|
||||
.lightLevel(state -> state.get(LIGHT_LEVEL)));
|
||||
setDefaultState(getDefaultState().with(LIGHT_LEVEL, 0));
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -134,16 +140,13 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
|
||||
// OPPOSITE!?
|
||||
}
|
||||
|
||||
// FIXME Dynamic light seems unsupported (?) Must maybe use blockstates... :|
|
||||
// FIXME FABRIC @Override
|
||||
// FIXME FABRIC public int getLightValue(final BlockState state, final BlockView world, final BlockPos pos) {
|
||||
// FIXME FABRIC if (state.getBlock() != this) {
|
||||
// FIXME FABRIC return state.getLuminance();
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC return this.cb(world, pos).getLightValue();
|
||||
// FIXME FABRIC }
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(LIGHT_LEVEL);
|
||||
}
|
||||
|
||||
// FIXME: Must hook isClimbing ourselves
|
||||
// FIXME: Must hook isClimbing ourselves
|
||||
// FIXME FABRIC @Override
|
||||
// FIXME FABRIC public boolean isLadder(BlockState state, WorldView world, BlockPos pos, LivingEntity entity) {
|
||||
// FIXME FABRIC return this.cb(world, pos).isLadder(entity);
|
||||
@@ -399,4 +402,13 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, CableBusBlockEntity te) {
|
||||
if (currentState.getBlock() != this) {
|
||||
return currentState;
|
||||
}
|
||||
int lightLevel = te.getCableBus().getLightValue();
|
||||
return super.updateBlockStateFromTileEntity(currentState, te).with(LIGHT_LEVEL, lightLevel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,10 +76,10 @@ class PaintSplotchesBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
if (s.isLumen()) {
|
||||
builder.setColorRGB(s.getColor().whiteVariant);
|
||||
builder.setRenderFullBright(true);
|
||||
builder.setEmissiveMaterial(true);
|
||||
} else {
|
||||
builder.setColorRGB(s.getColor().mediumVariant);
|
||||
builder.setRenderFullBright(false);
|
||||
builder.setEmissiveMaterial(false);
|
||||
}
|
||||
|
||||
float offset = offsetConstant;
|
||||
|
||||
@@ -144,7 +144,7 @@ class QnbFormedBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
if (formedState.isPowered()) {
|
||||
builder.setTexture(this.lightCornerTexture);
|
||||
builder.setRenderFullBright(true);
|
||||
builder.setEmissiveMaterial(true);
|
||||
for (Direction facing : Direction.values()) {
|
||||
// Offset the face by a slight amount so that it is drawn over the already drawn
|
||||
// ring texture
|
||||
@@ -158,6 +158,7 @@ class QnbFormedBakedModel implements BakedModel, FabricBakedModel {
|
||||
DEFAULT_RENDER_MIN - zOffset, DEFAULT_RENDER_MAX + xOffset,
|
||||
DEFAULT_RENDER_MAX + yOffset, DEFAULT_RENDER_MAX + zOffset);
|
||||
}
|
||||
builder.setEmissiveMaterial(false);
|
||||
}
|
||||
} else {
|
||||
builder.setTexture(this.ringTexture);
|
||||
@@ -170,7 +171,7 @@ class QnbFormedBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
if (formedState.isPowered()) {
|
||||
builder.setTexture(this.lightTexture);
|
||||
builder.setRenderFullBright(true);
|
||||
builder.setEmissiveMaterial(true);
|
||||
for (Direction facing : Direction.values()) {
|
||||
// Offset the face by a slight amount so that it is drawn over the already drawn
|
||||
// ring texture
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.google.common.base.Preconditions;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.Identifier;
|
||||
@@ -19,6 +18,7 @@ import net.minecraft.util.registry.Registry;
|
||||
|
||||
import appeng.api.features.AEFeature;
|
||||
import appeng.block.AEBaseTileBlock;
|
||||
import appeng.bootstrap.components.BlockEntityRendererComponent;
|
||||
import appeng.bootstrap.components.ITileEntityRegistrationComponent;
|
||||
import appeng.bootstrap.definitions.TileEntityDefinition;
|
||||
import appeng.core.AppEng;
|
||||
@@ -115,7 +115,8 @@ public class BlockEntityBuilder<T extends AEBaseBlockEntity> {
|
||||
@Environment(EnvType.CLIENT)
|
||||
private void buildClient() {
|
||||
if (tileEntityRendering.tileEntityRenderer != null) {
|
||||
BlockEntityRendererRegistry.INSTANCE.register(type, tileEntityRendering.tileEntityRenderer);
|
||||
factory.addBootstrapComponent(
|
||||
new BlockEntityRendererComponent<>(type, tileEntityRendering.tileEntityRenderer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package appeng.bootstrap.components;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
|
||||
/**
|
||||
* Registers a block entity renderer for a given block entity type. This must
|
||||
* occur late in the client's initialization, since the constructors of our
|
||||
* block entity renderers rely on the client being fully initialized.
|
||||
*/
|
||||
public class BlockEntityRendererComponent<T extends BlockEntity> implements IClientSetupComponent {
|
||||
|
||||
private final BlockEntityType<T> type;
|
||||
|
||||
private final Function<BlockEntityRenderDispatcher, BlockEntityRenderer<T>> renderer;
|
||||
|
||||
public BlockEntityRendererComponent(BlockEntityType<T> type,
|
||||
Function<BlockEntityRenderDispatcher, BlockEntityRenderer<T>> renderer) {
|
||||
this.type = type;
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
BlockEntityRendererRegistry.INSTANCE.register(type, renderer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
||||
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
|
||||
@@ -184,7 +185,9 @@ public final class AppEngClient extends AppEngBase {
|
||||
|
||||
ModelsReloadCallback.EVENT.register(this::onModelsReloaded);
|
||||
|
||||
callDeferredBootstrapComponents(IClientSetupComponent.class, IClientSetupComponent::setup);
|
||||
ClientLifecycleEvents.CLIENT_STARTED.register(client -> {
|
||||
callDeferredBootstrapComponents(IClientSetupComponent.class, IClientSetupComponent::setup);
|
||||
});
|
||||
registerModelProviders();
|
||||
registerParticleRenderers();
|
||||
registerEntityRenderers();
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -58,6 +59,7 @@ import net.minecraft.util.Identifier;
|
||||
import alexiil.mc.lib.attributes.fluid.render.FluidRenderFace;
|
||||
import alexiil.mc.lib.attributes.fluid.render.FluidVolumeRenderer;
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import me.shedaniel.math.Rectangle;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
@@ -803,4 +805,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
}
|
||||
}
|
||||
|
||||
public List<Rectangle> getExclusionZones() {
|
||||
return Lists.newArrayList(new Rectangle(x, y, backgroundWidth, backgroundHeight));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.client.me.SlotME;
|
||||
|
||||
/**
|
||||
* A proxy for a slot that will always return an itemstack with size 1, if there
|
||||
* is an item in the slot. Used to prevent the default item count from
|
||||
@@ -21,9 +19,9 @@ import appeng.client.me.SlotME;
|
||||
*/
|
||||
class Size1Slot extends Slot {
|
||||
|
||||
private final SlotME delegate;
|
||||
private final Slot delegate;
|
||||
|
||||
public Size1Slot(SlotME delegate) {
|
||||
public Size1Slot(Slot delegate) {
|
||||
super(delegate.inventory, -1, delegate.x, delegate.y);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
|
||||
str = Long.toString(stored.getStackSize() / 1000000) + 'm';
|
||||
}
|
||||
|
||||
str = GuiText.FromStorage.text() + ": " + str;
|
||||
str = GuiText.FromStorage.getLocal() + ": " + str;
|
||||
final int w = 4 + this.textRenderer.getWidth(str);
|
||||
this.textRenderer.draw(matrices, str,
|
||||
(int) ((x * (1 + sectionLength) + xo + sectionLength - 19 - (w * 0.5)) * 2),
|
||||
@@ -250,7 +250,7 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
|
||||
str = Long.toString(missingStack.getStackSize() / 1000000) + 'm';
|
||||
}
|
||||
|
||||
str = GuiText.Missing.text() + ": " + str;
|
||||
str = GuiText.Missing.getLocal() + ": " + str;
|
||||
final int w = 4 + this.textRenderer.getWidth(str);
|
||||
this.textRenderer.draw(matrices, str,
|
||||
(int) ((x * (1 + sectionLength) + xo + sectionLength - 19 - (w * 0.5)) * 2),
|
||||
@@ -273,7 +273,7 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
|
||||
str = Long.toString(pendingStack.getStackSize() / 1000000) + 'm';
|
||||
}
|
||||
|
||||
str = GuiText.ToCraft.text() + ": " + str;
|
||||
str = GuiText.ToCraft.getLocal() + ": " + str;
|
||||
final int w = 4 + this.textRenderer.getWidth(str);
|
||||
this.textRenderer.draw(matrices, str,
|
||||
(int) ((x * (1 + sectionLength) + xo + sectionLength - 19 - (w * 0.5)) * 2),
|
||||
|
||||
@@ -224,7 +224,7 @@ public class CraftingCPUScreen<T extends CraftingCPUContainer> extends AEBaseScr
|
||||
int downY = 0;
|
||||
|
||||
if (stored != null && stored.getStackSize() > 0) {
|
||||
final String str = GuiText.Stored.text() + ": "
|
||||
final String str = GuiText.Stored.getLocal() + ": "
|
||||
+ converter.toWideReadableForm(stored.getStackSize());
|
||||
final int w = 4 + this.textRenderer.getWidth(str);
|
||||
this.textRenderer.draw(matrices, str,
|
||||
@@ -240,7 +240,7 @@ public class CraftingCPUScreen<T extends CraftingCPUContainer> extends AEBaseScr
|
||||
}
|
||||
|
||||
if (activeStack != null && activeStack.getStackSize() > 0) {
|
||||
final String str = GuiText.Crafting.text() + ": "
|
||||
final String str = GuiText.Crafting.getLocal() + ": "
|
||||
+ converter.toWideReadableForm(activeStack.getStackSize());
|
||||
final int w = 4 + this.textRenderer.getWidth(str);
|
||||
|
||||
@@ -257,7 +257,7 @@ public class CraftingCPUScreen<T extends CraftingCPUContainer> extends AEBaseScr
|
||||
}
|
||||
|
||||
if (pendingStack != null && pendingStack.getStackSize() > 0) {
|
||||
final String str = GuiText.Scheduled.text() + ": "
|
||||
final String str = GuiText.Scheduled.getLocal() + ": "
|
||||
+ converter.toWideReadableForm(pendingStack.getStackSize());
|
||||
final int w = 4 + this.textRenderer.getWidth(str);
|
||||
|
||||
|
||||
@@ -89,7 +89,9 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
|
||||
this.searchField.setMaxLength(25);
|
||||
this.searchField.setEditableColor(0xFFFFFF);
|
||||
this.searchField.setVisible(true);
|
||||
this.searchField.setFocused(true);
|
||||
this.searchField.setChangedListener(str -> this.refreshList());
|
||||
this.addChild(this.searchField);
|
||||
this.changeFocus(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,11 +130,8 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(final double xCoord, final double yCoord, final int btn) {
|
||||
if (this.searchField.mouseClicked(xCoord, yCoord, btn)) {
|
||||
if (btn == 1 && this.searchField.isMouseOver(xCoord, yCoord)) {
|
||||
this.searchField.setText("");
|
||||
this.refreshList();
|
||||
}
|
||||
if (btn == 1 && this.searchField.isMouseOver(xCoord, yCoord)) {
|
||||
this.searchField.setText("");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -170,11 +169,7 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
|
||||
if (character == ' ' && this.searchField.getText().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (this.searchField.charTyped(character, key)) {
|
||||
this.refreshList();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return super.charTyped(character, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,8 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import me.shedaniel.math.Rectangle;
|
||||
|
||||
import appeng.api.config.SearchBoxMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.SortDir;
|
||||
@@ -519,4 +521,14 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
|
||||
this.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Rectangle> getExclusionZones() {
|
||||
List<Rectangle> zones = super.getExclusionZones();
|
||||
// Button toolbar on the left
|
||||
zones.add(new Rectangle(x - 18, y + 8, 18, 160));
|
||||
// View-cells on the right
|
||||
zones.add(new Rectangle(x + 197, y, 46, 128));
|
||||
return zones;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,10 +18,14 @@
|
||||
|
||||
package appeng.client.gui.implementations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import me.shedaniel.math.Rectangle;
|
||||
|
||||
import appeng.api.config.FuzzyMode;
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.SchedulingMode;
|
||||
@@ -146,4 +150,11 @@ public class UpgradeableScreen<T extends UpgradeableContainer> extends AEBaseScr
|
||||
return this.bc instanceof ImportBusPart ? GuiText.ImportBus : GuiText.ExportBus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Rectangle> getExclusionZones() {
|
||||
List<Rectangle> zones = super.getExclusionZones();
|
||||
zones.add(new Rectangle(x - 18, y + 8, 18, 60));
|
||||
return zones;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,9 +48,9 @@ public class WirelessScreen extends AEBaseScreen<WirelessContainer> {
|
||||
this.textRenderer.draw(matrices, GuiText.inventory.text(), 8, this.backgroundHeight - 96 + 3, 4210752);
|
||||
|
||||
if (handler.getRange() > 0) {
|
||||
final String firstMessage = GuiText.Range.text() + ": " + (handler.getRange() / 10.0) + " m";
|
||||
final String secondMessage = GuiText.PowerUsageRate.text() + ": "
|
||||
+ Platform.formatPowerLong(handler.getDrain(), true);
|
||||
final Text firstMessage = GuiText.Range.withSuffix(": " + (handler.getRange() / 10.0) + " m");
|
||||
final Text secondMessage = GuiText.PowerUsageRate
|
||||
.withSuffix(": " + Platform.formatPowerLong(handler.getDrain(), true));
|
||||
|
||||
final int strWidth = Math.max(this.textRenderer.getWidth(firstMessage),
|
||||
this.textRenderer.getWidth(secondMessage));
|
||||
|
||||
@@ -103,8 +103,8 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
|
||||
PowerUnits.AE.textComponent());
|
||||
registerApp(16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.EU, ButtonToolTips.PowerUnits,
|
||||
PowerUnits.EU.textComponent());
|
||||
registerApp(16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.RF, ButtonToolTips.PowerUnits,
|
||||
PowerUnits.RF.textComponent());
|
||||
registerApp(16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.TR, ButtonToolTips.PowerUnits,
|
||||
PowerUnits.TR.textComponent());
|
||||
|
||||
registerApp(3, Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE, ButtonToolTips.RedstoneMode,
|
||||
ButtonToolTips.AlwaysActive);
|
||||
|
||||
@@ -41,11 +41,6 @@ import appeng.fluids.util.FluidSorters;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.prioritylist.IPartitionList;
|
||||
|
||||
/**
|
||||
* @author BrockWS
|
||||
* @version rv6 - 22/05/2018
|
||||
* @since rv6 22/05/2018
|
||||
*/
|
||||
public class FluidRepo {
|
||||
private final IItemList<IAEFluidStack> list = Api.instance().storage().getStorageChannel(IFluidStorageChannel.class)
|
||||
.createList();
|
||||
|
||||
@@ -21,23 +21,22 @@ package appeng.client.me;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.inventory.SimpleInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.fluids.container.slots.IMEFluidSlot;
|
||||
|
||||
/**
|
||||
* @author BrockWS
|
||||
* @version rv6 - 22/05/2018
|
||||
* @since rv6 22/05/2018
|
||||
*/
|
||||
public class SlotFluidME extends Slot implements IMEFluidSlot {
|
||||
|
||||
private static final Inventory EMPTY_INVENTORY = new SimpleInventory(0);
|
||||
|
||||
private final InternalFluidSlotME slot;
|
||||
|
||||
public SlotFluidME(InternalFluidSlotME slot) {
|
||||
super(null, 0, slot.getxPosition(), slot.getyPosition());
|
||||
super(EMPTY_INVENTORY, 0, slot.getxPosition(), slot.getyPosition());
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
@@ -69,7 +68,7 @@ public class SlotFluidME extends Slot implements IMEFluidSlot {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(final ItemStack par1ItemStack) {
|
||||
public void setStack(final ItemStack stack) {
|
||||
|
||||
}
|
||||
|
||||
@@ -85,7 +84,7 @@ public class SlotFluidME extends Slot implements IMEFluidSlot {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
|
||||
public boolean canTakeItems(final PlayerEntity player) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
package appeng.client.me;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.inventory.SimpleInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
|
||||
@@ -26,16 +28,18 @@ import appeng.api.storage.data.IAEItemStack;
|
||||
|
||||
public class SlotME extends Slot {
|
||||
|
||||
private final InternalSlotME mySlot;
|
||||
private static final Inventory EMPTY_INVENTORY = new SimpleInventory(0);
|
||||
|
||||
public SlotME(final InternalSlotME me) {
|
||||
super(null, 0, me.getxPosition(), me.getyPosition());
|
||||
this.mySlot = me;
|
||||
private final InternalSlotME slot;
|
||||
|
||||
public SlotME(final InternalSlotME slot) {
|
||||
super(EMPTY_INVENTORY, 0, slot.getxPosition(), slot.getyPosition());
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public IAEItemStack getAEStack() {
|
||||
if (this.mySlot.hasPower()) {
|
||||
return this.mySlot.getAEStack();
|
||||
if (this.slot.hasPower()) {
|
||||
return this.slot.getAEStack();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -47,15 +51,15 @@ public class SlotME extends Slot {
|
||||
|
||||
@Override
|
||||
public ItemStack getStack() {
|
||||
if (this.mySlot.hasPower()) {
|
||||
return this.mySlot.getStack();
|
||||
if (this.slot.hasPower()) {
|
||||
return this.slot.getStack();
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStack() {
|
||||
if (this.mySlot.hasPower()) {
|
||||
if (this.slot.hasPower()) {
|
||||
return !this.getStack().isEmpty();
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -346,7 +346,7 @@ class CableBuilder {
|
||||
this.addBigCoveredCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Render the channel indicators brightly lit at night
|
||||
cubeBuilder.setRenderFullBright(true);
|
||||
cubeBuilder.setEmissiveMaterial(true);
|
||||
|
||||
cubeBuilder.setTexture(oddChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.blackVariant);
|
||||
@@ -357,14 +357,14 @@ class CableBuilder {
|
||||
this.addBigCoveredCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Reset back to normal rendering for the rest
|
||||
cubeBuilder.setRenderFullBright(false);
|
||||
cubeBuilder.setEmissiveMaterial(false);
|
||||
cubeBuilder.setTexture(texture);
|
||||
}
|
||||
|
||||
addCoveredCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Render the channel indicators brightly lit at night
|
||||
cubeBuilder.setRenderFullBright(true);
|
||||
cubeBuilder.setEmissiveMaterial(true);
|
||||
|
||||
cubeBuilder.setTexture(oddChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.blackVariant);
|
||||
@@ -373,6 +373,9 @@ class CableBuilder {
|
||||
cubeBuilder.setTexture(evenChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.whiteVariant);
|
||||
addCoveredCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Reset back to default
|
||||
cubeBuilder.setEmissiveMaterial(false);
|
||||
}
|
||||
|
||||
public void addStraightSmartConnection(Direction facing, AEColor cableColor, int channels, QuadEmitter emitter) {
|
||||
@@ -389,7 +392,7 @@ class CableBuilder {
|
||||
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
|
||||
|
||||
// Render the channel indicators brightly lit at night
|
||||
cubeBuilder.setRenderFullBright(true);
|
||||
cubeBuilder.setEmissiveMaterial(true);
|
||||
|
||||
cubeBuilder.setTexture(oddChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.blackVariant);
|
||||
@@ -398,6 +401,9 @@ class CableBuilder {
|
||||
cubeBuilder.setTexture(evenChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.whiteVariant);
|
||||
addStraightCoveredCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Reset back to default
|
||||
cubeBuilder.setEmissiveMaterial(false);
|
||||
}
|
||||
|
||||
public void addConstrainedSmartConnection(Direction facing, AEColor cableColor, int distanceFromEdge, int channels,
|
||||
@@ -420,7 +426,7 @@ class CableBuilder {
|
||||
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
|
||||
|
||||
// Render the channel indicators brightly lit at night
|
||||
cubeBuilder.setRenderFullBright(true);
|
||||
cubeBuilder.setEmissiveMaterial(true);
|
||||
|
||||
cubeBuilder.setTexture(oddChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.blackVariant);
|
||||
@@ -429,6 +435,9 @@ class CableBuilder {
|
||||
cubeBuilder.setTexture(evenChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.whiteVariant);
|
||||
addCoveredCableSizedCube(facing, distanceFromEdge, cubeBuilder);
|
||||
|
||||
// Reset back to default
|
||||
cubeBuilder.setEmissiveMaterial(false);
|
||||
}
|
||||
|
||||
public void addDenseCoveredConnection(Direction facing, AEColor cableColor, AECableType connectionType,
|
||||
@@ -452,7 +461,7 @@ class CableBuilder {
|
||||
addDenseCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Reset back to normal rendering for the rest
|
||||
cubeBuilder.setRenderFullBright(false);
|
||||
cubeBuilder.setEmissiveMaterial(false);
|
||||
cubeBuilder.setTexture(texture);
|
||||
}
|
||||
|
||||
@@ -488,7 +497,7 @@ class CableBuilder {
|
||||
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
|
||||
|
||||
// Render the channel indicators brightly lit at night
|
||||
cubeBuilder.setRenderFullBright(true);
|
||||
cubeBuilder.setEmissiveMaterial(true);
|
||||
|
||||
cubeBuilder.setTexture(oddChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.blackVariant);
|
||||
@@ -499,7 +508,7 @@ class CableBuilder {
|
||||
addDenseCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Reset back to normal rendering for the rest
|
||||
cubeBuilder.setRenderFullBright(false);
|
||||
cubeBuilder.setEmissiveMaterial(false);
|
||||
cubeBuilder.setTexture(texture);
|
||||
}
|
||||
|
||||
@@ -532,7 +541,7 @@ class CableBuilder {
|
||||
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
|
||||
|
||||
// Render the channel indicators brightly lit at night
|
||||
cubeBuilder.setRenderFullBright(true);
|
||||
cubeBuilder.setEmissiveMaterial(true);
|
||||
|
||||
cubeBuilder.setTexture(oddChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.blackVariant);
|
||||
@@ -541,6 +550,9 @@ class CableBuilder {
|
||||
cubeBuilder.setTexture(evenChannel);
|
||||
cubeBuilder.setColorRGB(cableColor.whiteVariant);
|
||||
addStraightDenseCableSizedCube(facing, cubeBuilder);
|
||||
|
||||
// Reset back to default
|
||||
cubeBuilder.setEmissiveMaterial(false);
|
||||
}
|
||||
|
||||
private static void addDenseCableSizedCube(Direction facing, CubeBuilder cubeBuilder) {
|
||||
|
||||
@@ -20,7 +20,6 @@ package appeng.client.render.cablebus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -30,6 +29,10 @@ import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
@@ -61,10 +64,15 @@ import appeng.api.util.AEColor;
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class CableBusBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
private static final Mesh EMPTY_MESH = consumer -> {
|
||||
};
|
||||
|
||||
private static final Renderer RENDERER = RendererAccess.INSTANCE.getRenderer();
|
||||
|
||||
// FIXME: This entire cache seems dumb as shit
|
||||
private static final Map<CableBusRenderState, Mesh> CABLE_MODEL_CACHE = new HashMap<>();
|
||||
// The number of meshes overall that will be cached
|
||||
private static final int CACHE_MESH_COUNT = 100;
|
||||
|
||||
private final LoadingCache<CableBusRenderState, Mesh> cableModelCache;
|
||||
|
||||
private final CableBuilder cableBuilder;
|
||||
|
||||
@@ -80,6 +88,15 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
|
||||
this.facadeBuilder = facadeBuilder;
|
||||
this.partModels = partModels;
|
||||
this.particleTexture = particleTexture;
|
||||
this.cableModelCache = CacheBuilder.newBuilder()//
|
||||
.maximumSize(CACHE_MESH_COUNT)//
|
||||
.build(new CacheLoader<CableBusRenderState, Mesh>() {
|
||||
@Override
|
||||
public Mesh load(CableBusRenderState renderState) {
|
||||
Mesh mesh = buildCableModel(renderState);
|
||||
return mesh != null ? mesh : EMPTY_MESH;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,8 +126,8 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
|
||||
}
|
||||
|
||||
// First, handle the cable at the center of the cable bus
|
||||
final Mesh cableModel = CABLE_MODEL_CACHE.computeIfAbsent(renderState, this::buildCableModel);
|
||||
if (cableModel != null) {
|
||||
final Mesh cableModel = cableModelCache.getUnchecked(renderState);
|
||||
if (cableModel != EMPTY_MESH) {
|
||||
context.meshConsumer().accept(cableModel);
|
||||
}
|
||||
|
||||
@@ -359,10 +376,6 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
public static void clearCache() {
|
||||
CABLE_MODEL_CACHE.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
|
||||
@@ -23,7 +23,6 @@ public class CableBusModelLoader implements ModelResourceProvider {
|
||||
public UnbakedModel loadModelResource(Identifier resourceId, ModelProviderContext context)
|
||||
throws ModelProviderException {
|
||||
if (CABLE_BUS_MODEL.equals(resourceId)) {
|
||||
CableBusBakedModel.clearCache();
|
||||
return new CableBusModel(partModels);
|
||||
} else {
|
||||
return null;
|
||||
|
||||
@@ -49,7 +49,7 @@ public class CubeBuilder {
|
||||
|
||||
private boolean useStandardUV = false;
|
||||
|
||||
private boolean renderFullBright;
|
||||
private boolean emissiveMaterial;
|
||||
|
||||
private final QuadEmitter emitter;
|
||||
|
||||
@@ -144,7 +144,7 @@ public class CubeBuilder {
|
||||
break;
|
||||
}
|
||||
|
||||
if (renderFullBright) {
|
||||
if (emissiveMaterial) {
|
||||
// Force Brightness to 15, this is for full bright mode
|
||||
// this vertex element will only be present in that case
|
||||
int lightmap = LightmapTextureManager.pack(15, 15);
|
||||
@@ -409,8 +409,8 @@ public class CubeBuilder {
|
||||
this.setColorRGB((int) (r * 255) << 16 | (int) (g * 255) << 8 | (int) (b * 255));
|
||||
}
|
||||
|
||||
public void setRenderFullBright(boolean renderFullBright) {
|
||||
this.renderFullBright = renderFullBright;
|
||||
public void setEmissiveMaterial(boolean renderFullBright) {
|
||||
this.emissiveMaterial = renderFullBright;
|
||||
}
|
||||
|
||||
public void setCustomUv(Direction facing, float u1, float v1, float u2, float v2) {
|
||||
|
||||
@@ -258,7 +258,9 @@ public class FacadeBuilder {
|
||||
|
||||
for (Box box : holeStrips) {
|
||||
emitter.fromVanilla(quad.getVertexData(), 0, false);
|
||||
emitter.cullFace(cullFace);
|
||||
// Keep the cull-face for faces that are flush with the outer block-face on the
|
||||
// side the facade is attached to, but clear it for anything that faces inwards
|
||||
emitter.cullFace(cullFace == side ? side : null);
|
||||
emitter.nominalFace(quad.getFace());
|
||||
interpolator.setInputQuad(emitter);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public class P2PTunnelFrequencyBakedModel implements IDynamicPartBakedModel {
|
||||
|
||||
cb.setTexture(this.texture);
|
||||
cb.useStandardUV();
|
||||
cb.setRenderFullBright(active);
|
||||
cb.setEmissiveMaterial(active);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
final int[] offs = QUAD_OFFSETS[i];
|
||||
@@ -89,6 +89,9 @@ public class P2PTunnelFrequencyBakedModel implements IDynamicPartBakedModel {
|
||||
|
||||
}
|
||||
|
||||
// Reset back to default
|
||||
cb.setEmissiveMaterial(false);
|
||||
|
||||
return meshBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Quaternion;
|
||||
@@ -93,10 +92,6 @@ public class QuadRotator implements RenderContext.QuadTransform {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME FABRIC: Wait for Grondags response about this one
|
||||
MutableQuadViewImpl quadImpl = (MutableQuadViewImpl) quad;
|
||||
quadImpl.lightFace(rotation.rotate(quad.lightFace()));
|
||||
|
||||
// Transform the nominal face, setting the cull face will also overwrite the
|
||||
// nominialFace,
|
||||
// hence saving both first and the order here.
|
||||
|
||||
@@ -50,8 +50,10 @@ class LightBakedModel extends CraftingCubeBakedModel {
|
||||
builder.addCube(x1, y1, z1, x2, y2, z2);
|
||||
|
||||
boolean powered = state.get(AbstractCraftingUnitBlock.POWERED);
|
||||
builder.setRenderFullBright(powered);
|
||||
builder.setEmissiveMaterial(powered);
|
||||
builder.setTexture(this.lightTexture);
|
||||
builder.addCube(x1, y1, z1, x2, y2, z2);
|
||||
// Reset back to default
|
||||
builder.setEmissiveMaterial(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class MonitorBakedModel extends CraftingCubeBakedModel {
|
||||
AEColor color = getColor(modelData);
|
||||
boolean powered = state.get(CraftingMonitorBlock.POWERED);
|
||||
|
||||
builder.setRenderFullBright(powered);
|
||||
builder.setEmissiveMaterial(powered);
|
||||
|
||||
builder.setColorRGB(color.whiteVariant);
|
||||
builder.setTexture(this.lightBrightTexture);
|
||||
@@ -90,6 +90,8 @@ public class MonitorBakedModel extends CraftingCubeBakedModel {
|
||||
builder.setTexture(this.lightDarkTexture);
|
||||
builder.addCube(x1, y1, z1, x2, y2, z2);
|
||||
|
||||
// Reset back to default
|
||||
builder.setEmissiveMaterial(false);
|
||||
}
|
||||
|
||||
private static AEColor getColor(CraftingCubeModelData modelData) {
|
||||
|
||||
@@ -127,7 +127,7 @@ class SpatialPylonBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
if ((flags
|
||||
& SpatialPylonBlockEntity.DISPLAY_POWERED_ENABLED) == SpatialPylonBlockEntity.DISPLAY_POWERED_ENABLED) {
|
||||
builder.setRenderFullBright(true);
|
||||
builder.setEmissiveMaterial(true);
|
||||
}
|
||||
|
||||
builder.setTextures(this.textures.get(getTextureTypeFromSideInside(flags, ori, Direction.UP)),
|
||||
@@ -144,6 +144,9 @@ class SpatialPylonBakedModel implements BakedModel, FabricBakedModel {
|
||||
builder.setTexture(this.textures.get(SpatialPylonTextureType.DIM));
|
||||
builder.addCube(0, 0, 0, 16, 16, 16);
|
||||
}
|
||||
|
||||
// Reset back to default
|
||||
builder.setEmissiveMaterial(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package appeng.client.render.tesr;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
@@ -9,12 +11,12 @@ import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
@@ -197,9 +199,12 @@ public final class InscriberTESR extends BlockEntityRenderer<InscriberBlockEntit
|
||||
|
||||
ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
|
||||
|
||||
// heuristic to scale items down much further than blocks
|
||||
boolean renderAsCube = (stack.getItem() instanceof BlockItem);
|
||||
if (!renderAsCube) {
|
||||
// heuristic to scale items down much further than blocks,
|
||||
// the assumption here is that the generated item models will return their faces
|
||||
// for direction=null, while a block-model will have their faces for
|
||||
// cull-faces, but not direction=null
|
||||
BakedModel model = itemRenderer.getModels().getModel(stack);
|
||||
if (!model.getQuads(null, null, new Random()).isEmpty()) {
|
||||
ms.scale(0.5f, 0.5f, 0.5f);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.LimitedFixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.SingleItemSlot;
|
||||
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.config.Settings;
|
||||
@@ -43,7 +45,7 @@ import appeng.api.networking.security.IActionHost;
|
||||
import appeng.container.AEBaseContainer;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.CompressedNBTPacket;
|
||||
import appeng.core.sync.packets.MEInterfaceUpdatePacket;
|
||||
import appeng.helpers.DualityInterface;
|
||||
import appeng.helpers.IInterfaceHost;
|
||||
import appeng.helpers.InventoryAction;
|
||||
@@ -57,8 +59,6 @@ import appeng.util.Platform;
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.AdaptorFixedInv;
|
||||
import appeng.util.inv.WrapperCursorItemHandler;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
|
||||
public final class InterfaceTerminalContainer extends AEBaseContainer {
|
||||
|
||||
@@ -177,7 +177,7 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
|
||||
|
||||
if (!this.data.isEmpty()) {
|
||||
try {
|
||||
NetworkHandler.instance().sendTo(new CompressedNBTPacket(this.data),
|
||||
NetworkHandler.instance().sendTo(new MEInterfaceUpdatePacket(this.data),
|
||||
(ServerPlayerEntity) this.getPlayerInv().player);
|
||||
} catch (final IOException e) {
|
||||
// :P
|
||||
@@ -196,35 +196,37 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
|
||||
|
||||
final InventoryAdaptor playerHand = new AdaptorFixedInv(new WrapperCursorItemHandler(player.inventory));
|
||||
|
||||
final FixedItemInv theSlot = new WrapperFilteredItemHandler(inv.server.getSubInv(slot, slot + 1),
|
||||
new PatternSlotFilter());
|
||||
final InventoryAdaptor interfaceSlot = new AdaptorFixedInv(theSlot);
|
||||
// Create a wrapper around the targetted slot that will only allow insertions of
|
||||
// patterns
|
||||
LimitedFixedItemInv limitedSlotInv = inv.server.createLimitedFixedInv();
|
||||
limitedSlotInv.getAllRule().filterInserts(this::isValidPattern);
|
||||
SingleItemSlot theSlot = limitedSlotInv.getSlot(slot);
|
||||
|
||||
switch (action) {
|
||||
case PICKUP_OR_SET_DOWN:
|
||||
|
||||
if (hasItemInHand) {
|
||||
ItemStack inSlot = theSlot.getInvStack(0);
|
||||
ItemStack inSlot = theSlot.get();
|
||||
if (inSlot.isEmpty()) {
|
||||
player.inventory.setCursorStack(interfaceSlot.addItems(player.inventory.getCursorStack()));
|
||||
player.inventory.setCursorStack(theSlot.insert(player.inventory.getCursorStack()));
|
||||
} else {
|
||||
inSlot = inSlot.copy();
|
||||
final ItemStack inHand = player.inventory.getCursorStack().copy();
|
||||
|
||||
ItemHandlerUtil.setStackInSlot(theSlot, 0, ItemStack.EMPTY);
|
||||
theSlot.set(ItemStack.EMPTY);
|
||||
player.inventory.setCursorStack(ItemStack.EMPTY);
|
||||
|
||||
player.inventory.setCursorStack(interfaceSlot.addItems(inHand.copy()));
|
||||
player.inventory.setCursorStack(theSlot.insert(inHand.copy()));
|
||||
|
||||
if (player.inventory.getCursorStack().isEmpty()) {
|
||||
player.inventory.setCursorStack(inSlot);
|
||||
} else {
|
||||
player.inventory.setCursorStack(inHand);
|
||||
ItemHandlerUtil.setStackInSlot(theSlot, 0, inSlot);
|
||||
theSlot.set(inSlot);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ItemHandlerUtil.setStackInSlot(theSlot, 0, playerHand.addItems(theSlot.getInvStack(0)));
|
||||
theSlot.set(playerHand.addItems(theSlot.get()));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -233,18 +235,18 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
|
||||
if (hasItemInHand) {
|
||||
ItemStack extra = playerHand.removeItems(1, ItemStack.EMPTY, null);
|
||||
if (!extra.isEmpty()) {
|
||||
extra = interfaceSlot.addItems(extra);
|
||||
extra = theSlot.insert(extra);
|
||||
}
|
||||
if (!extra.isEmpty()) {
|
||||
playerHand.addItems(extra);
|
||||
}
|
||||
} else if (!is.isEmpty()) {
|
||||
ItemStack extra = interfaceSlot.removeItems((is.getCount() + 1) / 2, ItemStack.EMPTY, null);
|
||||
ItemStack extra = theSlot.extract((is.getCount() + 1) / 2);
|
||||
if (!extra.isEmpty()) {
|
||||
extra = playerHand.addItems(extra);
|
||||
}
|
||||
if (!extra.isEmpty()) {
|
||||
interfaceSlot.addItems(extra);
|
||||
theSlot.insert(extra);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,8 +254,7 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
|
||||
case SHIFT_CLICK:
|
||||
|
||||
final InventoryAdaptor playerInv = InventoryAdaptor.getAdaptor(player);
|
||||
|
||||
ItemHandlerUtil.setStackInSlot(theSlot, 0, playerInv.addItems(theSlot.getInvStack(0)));
|
||||
theSlot.set(playerInv.addItems(theSlot.get()));
|
||||
|
||||
break;
|
||||
case MOVE_REGION:
|
||||
@@ -279,6 +280,10 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidPattern(ItemStack stack) {
|
||||
return !stack.isEmpty() && stack.getItem() instanceof EncodedPatternItem;
|
||||
}
|
||||
|
||||
private void regenList(final CompoundTag data) {
|
||||
this.byId.clear();
|
||||
this.diList.clear();
|
||||
@@ -369,15 +374,4 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
|
||||
}
|
||||
}
|
||||
|
||||
private static class PatternSlotFilter implements IAEItemFilter {
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
return !stack.isEmpty() && stack.getItem() instanceof EncodedPatternItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,13 +267,19 @@ public class PatternTermContainer extends MEMonitorableContainer
|
||||
return new ItemStack[] { out };
|
||||
}
|
||||
} else {
|
||||
boolean hasValue = false;
|
||||
final ItemStack[] list = new ItemStack[3];
|
||||
|
||||
for (int i = 0; i < this.outputSlots.length; i++) {
|
||||
final ItemStack out = this.outputSlots[i].getStack();
|
||||
list[i] = out;
|
||||
if (!out.isEmpty()) {
|
||||
hasValue = true;
|
||||
}
|
||||
}
|
||||
if (hasValue) {
|
||||
return list;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -143,9 +143,11 @@ public class QuartzKnifeContainer extends AEBaseContainer {
|
||||
|
||||
private void makePlate() {
|
||||
if (Platform.isServer()) {
|
||||
if (!this.takeStack(1).isEmpty()) {
|
||||
if (!inSlot.getSlot(0).extract(1).isEmpty()) {
|
||||
final ItemStack item = QuartzKnifeContainer.this.toolInv.getItemStack();
|
||||
final ItemStack before = item.copy();
|
||||
// FIXME FABRIC: Quartz Knife currently is not damageable due to recipe
|
||||
// remainder concerns
|
||||
item.damage(1, QuartzKnifeContainer.this.getPlayerInv().player, p -> {
|
||||
QuartzKnifeContainer.this.getPlayerInv()
|
||||
.setStack(QuartzKnifeContainer.this.getPlayerInv().selectedSlot, ItemStack.EMPTY);
|
||||
|
||||
@@ -165,7 +165,7 @@ public class RestrictedInputSlot extends AppEngSlot {
|
||||
case ORE:
|
||||
return GrinderRecipes.isValidIngredient(p.player.world, stack);
|
||||
case FUEL:
|
||||
return FuelRegistry.INSTANCE.get(stack.getItem()) > 0;
|
||||
return FuelRegistry.INSTANCE.get(stack.getItem()) != null;
|
||||
case POWERED_TOOL:
|
||||
return Platform.isChargeable(stack);
|
||||
case QE_SINGULARITY:
|
||||
|
||||
@@ -25,14 +25,14 @@ import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import appeng.api.config.CondenserOutput;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
@@ -50,6 +50,7 @@ import appeng.core.config.DoubleOption;
|
||||
import appeng.core.config.EnumOption;
|
||||
import appeng.core.config.IntegerOption;
|
||||
import appeng.core.config.StringListOption;
|
||||
import appeng.core.config.StringOption;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.util.EnumCycler;
|
||||
|
||||
@@ -81,13 +82,20 @@ public final class AEConfig {
|
||||
result.save(); // Save a default file
|
||||
} else {
|
||||
result.load();
|
||||
|
||||
// Re-save immediately to write-out new defaults
|
||||
try {
|
||||
result.save();
|
||||
} catch (Exception e) {
|
||||
AELog.warn(e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Default Energy Conversion Rates
|
||||
private static final double DEFAULT_IC2_EXCHANGE = 2.0;
|
||||
private static final double DEFAULT_RF_EXCHANGE = 0.5;
|
||||
private static final double DEFAULT_TR_EXCHANGE = 2.0;
|
||||
|
||||
public static final String VERSION = "@version@";
|
||||
public static final String CHANNEL = "@aechannel@";
|
||||
@@ -112,7 +120,6 @@ public final class AEConfig {
|
||||
private boolean useColoredCraftingStatus;
|
||||
private boolean disableColoredCableRecipesInJEI;
|
||||
private int craftingCalculationTimePerTick;
|
||||
private PowerUnits selectedPowerUnit = PowerUnits.AE;
|
||||
|
||||
// GUI Buttons
|
||||
private final int[] craftByStacks = new int[4];
|
||||
@@ -138,7 +145,6 @@ public final class AEConfig {
|
||||
|
||||
// Meteors
|
||||
private int meteoriteMaximumSpawnHeight;
|
||||
private Set<String> meteoriteDimensionWhitelist;
|
||||
|
||||
// Wireless
|
||||
private double wirelessBaseCost;
|
||||
@@ -157,9 +163,7 @@ public final class AEConfig {
|
||||
this.enableEffects = clientConfig.enableEffects.get();
|
||||
this.useLargeFonts = clientConfig.useLargeFonts.get();
|
||||
this.useColoredCraftingStatus = clientConfig.useColoredCraftingStatus.get();
|
||||
this.selectedPowerUnit = clientConfig.selectedPowerUnit.get();
|
||||
|
||||
// load buttons..
|
||||
for (int btnNum = 0; btnNum < 4; btnNum++) {
|
||||
this.craftByStacks[btnNum] = clientConfig.craftByStacks.get(btnNum).get();
|
||||
this.priorityByStacks[btnNum] = clientConfig.priorityByStacks.get(btnNum).get();
|
||||
@@ -169,7 +173,7 @@ public final class AEConfig {
|
||||
|
||||
private void syncCommonConfig() {
|
||||
PowerUnits.EU.conversionRatio = commonConfig.powerRatioIc2.get();
|
||||
PowerUnits.RF.conversionRatio = commonConfig.powerRatioForgeEnergy.get();
|
||||
PowerUnits.TR.conversionRatio = commonConfig.powerRatioTechReborn.get();
|
||||
PowerMultiplier.CONFIG.multiplier = commonConfig.powerUsageMultiplier.get();
|
||||
|
||||
CondenserOutput.MATTER_BALLS.requiredPower = commonConfig.condenserMatterBallsPower.get();
|
||||
@@ -178,7 +182,6 @@ public final class AEConfig {
|
||||
this.oreDoublePercentage = (float) commonConfig.oreDoublePercentage.get();
|
||||
|
||||
this.meteoriteMaximumSpawnHeight = commonConfig.meteoriteMaximumSpawnHeight.get();
|
||||
this.meteoriteDimensionWhitelist = new HashSet<>(commonConfig.meteoriteDimensionWhitelist.get());
|
||||
|
||||
this.wirelessBaseCost = commonConfig.wirelessBaseCost.get();
|
||||
this.wirelessCostMultiplier = commonConfig.wirelessCostMultiplier.get();
|
||||
@@ -271,7 +274,6 @@ public final class AEConfig {
|
||||
}
|
||||
|
||||
public void save() {
|
||||
clientConfig.selectedPowerUnit.set(this.selectedPowerUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,7 +301,7 @@ public final class AEConfig {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void nextPowerUnit(final boolean backwards) {
|
||||
PowerUnits selectedPowerUnit = EnumCycler.rotateEnum(this.selectedPowerUnit, backwards,
|
||||
PowerUnits selectedPowerUnit = EnumCycler.rotateEnum(getSelectedPowerUnit(), backwards,
|
||||
(EnumSet<PowerUnits>) Settings.POWER_UNITS.getPossibleValues());
|
||||
clientConfig.selectedPowerUnit.set(selectedPowerUnit);
|
||||
}
|
||||
@@ -373,6 +375,10 @@ public final class AEConfig {
|
||||
return () -> this.chargedStaffBattery;
|
||||
}
|
||||
|
||||
public double getPowerTransactionLimitTechReborn() {
|
||||
return commonConfig.powerTransactionLimitTechReborn.get();
|
||||
}
|
||||
|
||||
public float getSpawnChargedChance() {
|
||||
return (float) commonConfig.spawnChargedChance.get();
|
||||
}
|
||||
@@ -389,8 +395,21 @@ public final class AEConfig {
|
||||
return this.meteoriteMaximumSpawnHeight;
|
||||
}
|
||||
|
||||
public Set<String> getMeteoriteDimensionWhitelist() {
|
||||
return this.meteoriteDimensionWhitelist;
|
||||
public List<String> getMeteoriteBiomeBlacklist() {
|
||||
return commonConfig.meteoriteBiomeBlacklist.get();
|
||||
}
|
||||
|
||||
public List<String> getQuartzOreBiomeBlacklist() {
|
||||
return commonConfig.quartzOreBiomeBlacklist.get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getImprovedFluidTag() {
|
||||
return Strings.emptyToNull(commonConfig.improvedFluidTag.get());
|
||||
}
|
||||
|
||||
public float getImprovedFluidMultiplier() {
|
||||
return (float) commonConfig.improvedFluidMultiplier.get();
|
||||
}
|
||||
|
||||
// Setters keep visibility as low as possible.
|
||||
@@ -478,10 +497,11 @@ public final class AEConfig {
|
||||
public final DoubleOption spawnChargedChance;
|
||||
public final IntegerOption quartzOresPerCluster;
|
||||
public final IntegerOption quartzOresClusterAmount;
|
||||
public final StringListOption quartzOreBiomeBlacklist;
|
||||
|
||||
// Meteors
|
||||
public final IntegerOption meteoriteMaximumSpawnHeight;
|
||||
public final StringListOption meteoriteDimensionWhitelist;
|
||||
public final StringListOption meteoriteBiomeBlacklist;
|
||||
|
||||
// Wireless
|
||||
public final DoubleOption wirelessBaseCost;
|
||||
@@ -494,13 +514,21 @@ public final class AEConfig {
|
||||
|
||||
// Power Ratios
|
||||
public final DoubleOption powerRatioIc2;
|
||||
public final DoubleOption powerRatioForgeEnergy;
|
||||
public final DoubleOption powerRatioTechReborn;
|
||||
public final DoubleOption powerUsageMultiplier;
|
||||
|
||||
// How much TR energy can be transfered at most in one operation
|
||||
public final DoubleOption powerTransactionLimitTechReborn;
|
||||
|
||||
// Condenser Power Requirement
|
||||
public final IntegerOption condenserMatterBallsPower;
|
||||
public final IntegerOption condenserSingularityPower;
|
||||
|
||||
// In-World Purification
|
||||
// Settings for improved speed depending on fluid the crystal is in
|
||||
public final StringOption improvedFluidTag;
|
||||
public final DoubleOption improvedFluidMultiplier;
|
||||
|
||||
public final Map<TickRates, IntegerOption> tickRateMin = new HashMap<>();
|
||||
public final Map<TickRates, IntegerOption> tickRateMax = new HashMap<>();
|
||||
|
||||
@@ -559,13 +587,13 @@ public final class AEConfig {
|
||||
|
||||
this.spawnChargedChance = worldGen.addDouble("spawnChargedChance", 0.08, 0.0, 1.0);
|
||||
this.meteoriteMaximumSpawnHeight = worldGen.addInt("meteoriteMaximumSpawnHeight", 180);
|
||||
List<String> defaultDimensionWhitelist = new ArrayList<>();
|
||||
defaultDimensionWhitelist.add(DimensionType.OVERWORLD_REGISTRY_KEY.getValue().toString());
|
||||
this.meteoriteDimensionWhitelist = worldGen.addStringList("meteoriteDimensionWhitelist",
|
||||
defaultDimensionWhitelist);
|
||||
this.meteoriteBiomeBlacklist = worldGen.addStringList("meteoriteBiomeBlacklist", new ArrayList<>(),
|
||||
"Biome IDs in which meteorites should NOT be generated (i.e. minecraft:plains).");
|
||||
|
||||
this.quartzOresPerCluster = worldGen.addInt("quartzOresPerCluster", 4);
|
||||
this.quartzOresClusterAmount = worldGen.addInt("quartzOresClusterAmount", 20);
|
||||
this.quartzOreBiomeBlacklist = worldGen.addStringList("quartzOreBiomeBlacklist", new ArrayList<>(),
|
||||
"Biome IDs in which quartz ores should NOT be generated (i.e. minecraft:plains).");
|
||||
|
||||
ConfigSection wireless = root.subsection("wireless");
|
||||
this.wirelessBaseCost = wireless.addDouble("wirelessBaseCost", 8.0);
|
||||
@@ -578,9 +606,13 @@ public final class AEConfig {
|
||||
|
||||
ConfigSection PowerRatios = root.subsection("PowerRatios");
|
||||
powerRatioIc2 = PowerRatios.addDouble("IC2", DEFAULT_IC2_EXCHANGE);
|
||||
powerRatioForgeEnergy = PowerRatios.addDouble("ForgeEnergy", DEFAULT_RF_EXCHANGE);
|
||||
powerRatioTechReborn = PowerRatios.addDouble("TechReborn", DEFAULT_TR_EXCHANGE);
|
||||
powerUsageMultiplier = PowerRatios.addDouble("UsageMultiplier", 1.0, 0.01, Double.MAX_VALUE);
|
||||
|
||||
ConfigSection integration = root.subsection("Integration");
|
||||
powerTransactionLimitTechReborn = integration.addDouble("MaxTechRebornEnergyPerTransaction", 10000.0, 0.1,
|
||||
1000000.0, "The maximum amount of TechReborn energy units that can be transfered per operation.");
|
||||
|
||||
ConfigSection Condenser = root.subsection("Condenser");
|
||||
condenserMatterBallsPower = Condenser.addInt("MatterBalls", 256);
|
||||
condenserSingularityPower = Condenser.addInt("Singularity", 256000);
|
||||
@@ -591,6 +623,14 @@ public final class AEConfig {
|
||||
tickRateMin.put(tickRate, tickrates.addInt(tickRate.name() + "Min", tickRate.getDefaultMin()));
|
||||
tickRateMax.put(tickRate, tickrates.addInt(tickRate.name() + "Max", tickRate.getDefaultMax()));
|
||||
}
|
||||
|
||||
ConfigSection inWorldPurification = root.subsection("inWorldPurification",
|
||||
"Settings for in-world purification of crystals.");
|
||||
|
||||
improvedFluidTag = inWorldPurification.addString("improvedFluidTag", "",
|
||||
"A fluid tag that identifies fluids that improve crystal purification speed. Does not affect purification with water/lava.");
|
||||
improvedFluidMultiplier = inWorldPurification.addDouble("improvedFluidMultiplier", 2.0, 1.0, 10.0,
|
||||
"The speed multiplier to use when the crystals are submerged in the improved fluid.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,10 +30,8 @@ import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.definitions.IBlocks;
|
||||
@@ -41,7 +39,6 @@ import appeng.api.definitions.IItems;
|
||||
import appeng.api.definitions.IParts;
|
||||
import appeng.api.features.IRegistryContainer;
|
||||
import appeng.api.features.IWirelessTermHandler;
|
||||
import appeng.api.features.IWorldGen;
|
||||
import appeng.api.movable.IMovableRegistry;
|
||||
import appeng.api.networking.IGridCacheRegistry;
|
||||
import appeng.api.networking.crafting.ICraftingGrid;
|
||||
@@ -108,6 +105,7 @@ import appeng.fluids.container.FluidStorageBusContainer;
|
||||
import appeng.fluids.container.FluidTerminalContainer;
|
||||
import appeng.fluids.registries.BasicFluidCellGuiHandler;
|
||||
import appeng.hooks.ToolItemHook;
|
||||
import appeng.integration.modules.trenergy.ItemPowerStorageAdapter;
|
||||
import appeng.items.parts.FacadeItem;
|
||||
import appeng.items.tools.NetworkToolItem;
|
||||
import appeng.me.cache.CraftingGridCache;
|
||||
@@ -164,6 +162,7 @@ public abstract class AppEngBase implements AppEng {
|
||||
|
||||
setupInternalRegistries();
|
||||
|
||||
ItemPowerStorageAdapter.register();
|
||||
}
|
||||
|
||||
public static void setupInternalRegistries() {
|
||||
@@ -343,21 +342,6 @@ public abstract class AppEngBase implements AppEng {
|
||||
*/
|
||||
mr.whiteListBlockEntity(AEBaseBlockEntity.class);
|
||||
|
||||
/*
|
||||
* world gen
|
||||
*/
|
||||
for (final IWorldGen.WorldGenType type : IWorldGen.WorldGenType.values()) {
|
||||
// FIXME: registries.worldgen().disableWorldGenForProviderID( type,
|
||||
// StorageWorldProvider.class );
|
||||
|
||||
registries.worldgen().disableWorldGenForDimension(type, DimensionType.THE_NETHER_REGISTRY_KEY.getValue());
|
||||
}
|
||||
|
||||
// whitelist from config
|
||||
for (final String dimension : AEConfig.instance().getMeteoriteDimensionWhitelist()) {
|
||||
registries.worldgen().enableWorldGenForDimension(IWorldGen.WorldGenType.METEORITES,
|
||||
new Identifier(dimension));
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerParticleTypes() {
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
package appeng.core;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.BuiltinRegistries;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.GenerationStep;
|
||||
import net.minecraft.world.gen.decorator.Decorator;
|
||||
@@ -54,11 +61,21 @@ public final class AppEngBootstrap {
|
||||
ConfiguredFeature<?, ?> quartzOreFeature = registerQuartzOreFeature();
|
||||
ConfiguredFeature<?, ?> chargedQuartzOreFeature = registerChargedQuartzOreFeature();
|
||||
|
||||
// add to all standard biomes
|
||||
// TODO: This means we'll not add these things to newly created biomes
|
||||
BuiltinRegistries.BIOME.forEach(b -> {
|
||||
addMeteoriteWorldGen(b);
|
||||
addQuartzWorldGen(b, quartzOreFeature, chargedQuartzOreFeature);
|
||||
Set<String> meteoriteBiomeBlacklist = new HashSet<>(AEConfig.instance().getMeteoriteBiomeBlacklist());
|
||||
Set<String> quartzOreBiomeBlacklist = new HashSet<>(AEConfig.instance().getQuartzOreBiomeBlacklist());
|
||||
|
||||
// Add features to all existing biomes
|
||||
for (Map.Entry<RegistryKey<Biome>, Biome> entry : BuiltinRegistries.BIOME.getEntries()) {
|
||||
Identifier id = entry.getKey().getValue();
|
||||
Biome b = entry.getValue();
|
||||
addMeteoriteWorldGen(id, b, meteoriteBiomeBlacklist);
|
||||
addQuartzWorldGen(id, b, quartzOreFeature, chargedQuartzOreFeature, quartzOreBiomeBlacklist);
|
||||
}
|
||||
|
||||
// Listen to added biomes for post-processing
|
||||
RegistryEntryAddedCallback.event(BuiltinRegistries.BIOME).register((i, id, biome) -> {
|
||||
addMeteoriteWorldGen(id, biome, meteoriteBiomeBlacklist);
|
||||
addQuartzWorldGen(id, biome, quartzOreFeature, chargedQuartzOreFeature, quartzOreBiomeBlacklist);
|
||||
});
|
||||
|
||||
registerDimension();
|
||||
@@ -78,12 +95,19 @@ public final class AppEngBootstrap {
|
||||
MeteoriteStructure.CONFIGURED_INSTANCE);
|
||||
}
|
||||
|
||||
private static void addMeteoriteWorldGen(Biome b) {
|
||||
private static void addMeteoriteWorldGen(Identifier id, Biome b, Set<String> biomeBlacklist) {
|
||||
if (!AEConfig.instance().isFeatureEnabled(AEFeature.METEORITE_WORLD_GEN)) {
|
||||
AELog.debug("Not generating meteorites in %s because the feature is disabled", id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (b.getCategory() == Biome.Category.THEEND || b.getCategory() == Biome.Category.NETHER) {
|
||||
AELog.debug("Not generating meteorites in %s because it's of category %s", id, b.getCategory());
|
||||
return;
|
||||
}
|
||||
|
||||
if (biomeBlacklist.contains(id.toString())) {
|
||||
AELog.debug("Not generating meteorites in %s because the biome is blacklisted in the config", id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -91,14 +115,24 @@ public final class AppEngBootstrap {
|
||||
modifier.addStructureFeature(MeteoriteStructure.CONFIGURED_INSTANCE);
|
||||
}
|
||||
|
||||
private static void addQuartzWorldGen(Biome b, ConfiguredFeature<?, ?> quartzOre,
|
||||
ConfiguredFeature<?, ?> chargedQuartz) {
|
||||
private static void addQuartzWorldGen(Identifier id, Biome b, ConfiguredFeature<?, ?> quartzOre,
|
||||
ConfiguredFeature<?, ?> chargedQuartz, Set<String> biomeBlacklist) {
|
||||
if (!AEConfig.instance().isFeatureEnabled(AEFeature.CERTUS_QUARTZ_WORLD_GEN)) {
|
||||
AELog.debug("Not generating quartz-ore in %s because the feature is disabled", id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (b.getCategory() == Biome.Category.THEEND || b.getCategory() == Biome.Category.NETHER) {
|
||||
AELog.debug("Not generating quartz ore in %s because it's of category %s", id, b.getCategory());
|
||||
return;
|
||||
}
|
||||
|
||||
if (biomeBlacklist.contains(id.toString())) {
|
||||
AELog.debug("Not generating quartz-ore in %s because the biome is blacklisted in the config", id);
|
||||
return;
|
||||
}
|
||||
|
||||
BiomeModifier modifier = new BiomeModifier(b);
|
||||
|
||||
modifier.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, quartzOre);
|
||||
|
||||
if (AEConfig.instance().isFeatureEnabled(AEFeature.CHARGED_CERTUS_ORE)) {
|
||||
|
||||
@@ -115,7 +115,12 @@ public class ApiCrafting implements ICraftingHelper {
|
||||
// We use the shared itemstack for an identity lookup.
|
||||
IAEItemStack ais = Api.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(is);
|
||||
|
||||
return new CraftingPatternDetails(ais, world);
|
||||
try {
|
||||
return new CraftingPatternDetails(ais, world);
|
||||
} catch (IllegalStateException e) {
|
||||
AELog.warn("Could not decode an invalid pattern %s: %s", is, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean attemptRecovery(EncodedPatternItem patternItem, ItemStack itemStack, World world) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import net.minecraft.block.Material;
|
||||
import net.minecraft.block.SlabBlock;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.entity.EntityDimensions;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.SpawnGroup;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
|
||||
@@ -267,17 +268,19 @@ public final class ApiBlocks implements IBlocks {
|
||||
this.chiseledQuartzBlock = deco.block("chiseled_quartz_block", () -> new AEDecorativeBlock(QUARTZ_PROPERTIES))
|
||||
.build();
|
||||
|
||||
this.quartzGlass = registry.features(AEFeature.QUARTZ_GLASS)
|
||||
.block("quartz_glass", () -> new QuartzGlassBlock(glassProps()))
|
||||
.rendering(new BlockRenderingCustomizer() {
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
|
||||
rendering.renderType(RenderLayer.getCutout());
|
||||
}
|
||||
}).build();
|
||||
AbstractBlock.TypedContextPredicate<EntityType<?>> neverAllowSpawn = (p1, p2, p3, p4) -> false;
|
||||
this.quartzGlass = registry.features(AEFeature.QUARTZ_GLASS).block("quartz_glass", () -> {
|
||||
return new QuartzGlassBlock(glassProps().allowsSpawning(neverAllowSpawn));
|
||||
}).rendering(new BlockRenderingCustomizer() {
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
|
||||
rendering.renderType(RenderLayer.getCutout());
|
||||
}
|
||||
}).build();
|
||||
this.quartzVibrantGlass = deco
|
||||
.block("quartz_vibrant_glass", () -> new QuartzLampBlock(glassProps().lightLevel(15)))
|
||||
.block("quartz_vibrant_glass",
|
||||
() -> new QuartzLampBlock(glassProps().lightLevel(15).allowsSpawning(neverAllowSpawn)))
|
||||
.addFeatures(AEFeature.DECORATIVE_LIGHTS, AEFeature.QUARTZ_GLASS)
|
||||
.rendering(new BlockRenderingCustomizer() {
|
||||
@Override
|
||||
|
||||
@@ -55,6 +55,7 @@ import appeng.hooks.BlockToolDispenseItemBehavior;
|
||||
import appeng.hooks.MatterCannonDispenseItemBehavior;
|
||||
import appeng.items.materials.MaterialType;
|
||||
import appeng.items.misc.CrystalSeedItem;
|
||||
import appeng.items.misc.CrystalSeedRendering;
|
||||
import appeng.items.misc.EncodedPatternItem;
|
||||
import appeng.items.misc.PaintBallItem;
|
||||
import appeng.items.misc.PaintBallItemRendering;
|
||||
@@ -140,12 +141,12 @@ public final class ApiItems implements IItems {
|
||||
private final AEColoredItemDefinition coloredLumenPaintBall;
|
||||
|
||||
// unsupported dev tools
|
||||
private IItemDefinition toolEraser;
|
||||
private IItemDefinition toolMeteoritePlacer;
|
||||
private IItemDefinition toolDebugCard;
|
||||
private IItemDefinition toolReplicatorCard;
|
||||
private final IItemDefinition toolEraser;
|
||||
private final IItemDefinition toolMeteoritePlacer;
|
||||
private final IItemDefinition toolDebugCard;
|
||||
private final IItemDefinition toolReplicatorCard;
|
||||
|
||||
private IItemDefinition dummyFluidItem;
|
||||
private final IItemDefinition dummyFluidItem;
|
||||
|
||||
public ApiItems(FeatureFactory registry, ApiMaterials materials) {
|
||||
FeatureFactory certusTools = registry.features(AEFeature.CERTUS_QUARTZ_TOOLS);
|
||||
@@ -305,28 +306,19 @@ public final class ApiItems implements IItems {
|
||||
this.certusCrystalSeed = registry
|
||||
.item("certus_crystal_seed",
|
||||
props -> new CrystalSeedItem(props, materials.purifiedCertusQuartzCrystal().item()))
|
||||
.bootstrap(item -> new IClientSetupComponent() {
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void setup() {
|
||||
// Expose the growth of the seed to the model system
|
||||
FabricModelPredicateProviderRegistry.register(item, AppEng.makeId("growth"),
|
||||
(is, w, p) -> CrystalSeedItem.getGrowthTicks(is)
|
||||
/ (float) CrystalSeedItem.GROWTH_TICKS_REQUIRED);
|
||||
}
|
||||
}).features(AEFeature.CRYSTAL_SEEDS).build();
|
||||
.bootstrap(CrystalSeedRendering::new).features(AEFeature.CRYSTAL_SEEDS).build();
|
||||
this.fluixCrystalSeed = registry
|
||||
.item("fluix_crystal_seed",
|
||||
props -> new CrystalSeedItem(props, materials.purifiedFluixCrystal().item()))
|
||||
.features(AEFeature.CRYSTAL_SEEDS).build();
|
||||
.bootstrap(CrystalSeedRendering::new).features(AEFeature.CRYSTAL_SEEDS).build();
|
||||
this.netherQuartzSeed = registry
|
||||
.item("nether_quartz_seed",
|
||||
props -> new CrystalSeedItem(props, materials.purifiedNetherQuartzCrystal().item()))
|
||||
.features(AEFeature.CRYSTAL_SEEDS).build();
|
||||
.bootstrap(CrystalSeedRendering::new).features(AEFeature.CRYSTAL_SEEDS).build();
|
||||
|
||||
GrowingCrystalEntity.TYPE = registry
|
||||
.<GrowingCrystalEntity>entity("growing_crystal", GrowingCrystalEntity::new, SpawnGroup.MISC)
|
||||
.customize(builder -> builder.dimensions(EntityDimensions.fixed(0.25F, 0.25F))).build();
|
||||
.customize(builder -> builder.dimensions(EntityDimensions.fixed(0.25F, 0.4F))).build();
|
||||
|
||||
// rv1
|
||||
this.encodedPattern = registry.item("encoded_pattern", EncodedPatternItem::new)
|
||||
|
||||
@@ -105,8 +105,6 @@ public final class ApiParts implements IParts {
|
||||
private final IItemDefinition p2PTunnelRedstone;
|
||||
private final IItemDefinition p2PTunnelItems;
|
||||
private final IItemDefinition p2PTunnelFluids;
|
||||
private final IItemDefinition p2PTunnelEU;
|
||||
private final IItemDefinition p2PTunnelFE;
|
||||
private final IItemDefinition p2PTunnelLight;
|
||||
private final IItemDefinition cableAnchor;
|
||||
private final IItemDefinition monitor;
|
||||
@@ -176,17 +174,11 @@ public final class ApiParts implements IParts {
|
||||
RedstoneP2PTunnelPart::new);
|
||||
this.p2PTunnelItems = createPart("item_p2p_tunnel", ItemP2PTunnelPart.class, ItemP2PTunnelPart::new);
|
||||
this.p2PTunnelFluids = createPart("fluid_p2p_tunnel", FluidP2PTunnelPart.class, FluidP2PTunnelPart::new);
|
||||
// FIXME FABRIC this.p2PTunnelEU = null; // FIXME createPart( "ic2_p2p_tunnel", PartType.P2P_TUNNEL_IC2,
|
||||
// FIXME FABRIC // PartP2PIC2Power.class, PartP2PIC2Power::new);
|
||||
// FIXME FABRIC this.p2PTunnelFE = createPart("fe_p2p_tunnel", FEP2PTunnelPart.class, FEP2PTunnelPart::new);
|
||||
this.p2PTunnelLight = createPart("light_p2p_tunnel", LightP2PTunnelPart.class, LightP2PTunnelPart::new);
|
||||
this.interfaceTerminal = createPart("interface_terminal", InterfaceTerminalPart.class,
|
||||
InterfaceTerminalPart::new);
|
||||
this.fluidTerminal = createPart("fluid_terminal", FluidTerminalPart.class, FluidTerminalPart::new);
|
||||
|
||||
this.p2PTunnelEU = null;
|
||||
this.p2PTunnelFE = null;
|
||||
|
||||
this.registry = null;
|
||||
this.partModels = null;
|
||||
}
|
||||
@@ -324,16 +316,6 @@ public final class ApiParts implements IParts {
|
||||
return this.p2PTunnelFluids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemDefinition p2PTunnelEU() {
|
||||
return this.p2PTunnelEU;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemDefinition p2PTunnelFE() {
|
||||
return this.p2PTunnelFE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemDefinition p2PTunnelLight() {
|
||||
return this.p2PTunnelLight;
|
||||
|
||||
@@ -58,6 +58,14 @@ public class ConfigSection {
|
||||
return option;
|
||||
}
|
||||
|
||||
public StringOption addString(String id, String defaultValue) {
|
||||
return addString(id, defaultValue, comment);
|
||||
}
|
||||
|
||||
public StringOption addString(String id, String defaultValue, String comment) {
|
||||
return addOption(new StringOption(this, id, comment, defaultValue));
|
||||
}
|
||||
|
||||
public IntegerOption addInt(String id, int defaultValue) {
|
||||
return addInt(id, defaultValue, comment);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package appeng.core.config;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
public class StringOption extends BaseOption {
|
||||
|
||||
private final String defaultValue;
|
||||
private String currentValue;
|
||||
|
||||
public StringOption(ConfigSection parent, String id, String comment, String defaultValue) {
|
||||
super(parent, id, comment);
|
||||
this.defaultValue = defaultValue;
|
||||
this.currentValue = this.defaultValue;
|
||||
}
|
||||
|
||||
public String get() {
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
public void set(String value) {
|
||||
Preconditions.checkNotNull(value);
|
||||
if (value.equals(currentValue)) {
|
||||
return;
|
||||
}
|
||||
currentValue = value;
|
||||
parent.markDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsonElement write() {
|
||||
return new JsonPrimitive(currentValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(JsonElement element) {
|
||||
if (!element.isJsonPrimitive()) {
|
||||
throw new ConfigValidationException(this, "Expected a JSON primitive: " + element);
|
||||
}
|
||||
JsonPrimitive primitive = element.getAsJsonPrimitive();
|
||||
if (!primitive.isString()) {
|
||||
throw new ConfigValidationException(this, "Expected a JSON string, but found: " + primitive);
|
||||
}
|
||||
|
||||
this.currentValue = primitive.getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDifferentFromDefault() {
|
||||
return !currentValue.equals(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultAsString() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentValueAsString() {
|
||||
return currentValue;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import appeng.api.events.LocatableEventAnnounce;
|
||||
import appeng.api.events.LocatableEventAnnounce.LocatableEvent;
|
||||
import appeng.api.features.ILocatable;
|
||||
import appeng.api.features.ILocatableRegistry;
|
||||
import appeng.core.AELog;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public final class LocatableRegistry implements ILocatableRegistry {
|
||||
@@ -39,8 +40,10 @@ public final class LocatableRegistry implements ILocatableRegistry {
|
||||
}
|
||||
|
||||
if (change == LocatableEvent.REGISTER) {
|
||||
AELog.debug("Registering locatable %s: %s", target.getLocatableSerial(), target);
|
||||
this.set.put(target.getLocatableSerial(), target);
|
||||
} else if (change == LocatableEvent.UNREGISTER) {
|
||||
AELog.debug("Unregistering locatable %s: %s", target.getLocatableSerial(), target);
|
||||
this.set.remove(target.getLocatableSerial());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -63,32 +63,6 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry {
|
||||
this.addNewAttunement(new ItemStack(Blocks.TORCH), TunnelType.LIGHT);
|
||||
this.addNewAttunement(new ItemStack(Blocks.GLOWSTONE), TunnelType.LIGHT);
|
||||
|
||||
/*
|
||||
* Forge energy tunnel items
|
||||
*/
|
||||
|
||||
this.addNewAttunement(blocks.energyCellDense(), TunnelType.FE_POWER);
|
||||
this.addNewAttunement(blocks.energyAcceptor(), TunnelType.FE_POWER);
|
||||
this.addNewAttunement(blocks.energyCell(), TunnelType.FE_POWER);
|
||||
this.addNewAttunement(blocks.energyCellCreative(), TunnelType.FE_POWER);
|
||||
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_0", 0 ), TunnelType.FE_POWER );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_0", 1 ), TunnelType.FE_POWER );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_0", 2 ), TunnelType.FE_POWER );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_0", 3 ), TunnelType.FE_POWER );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_0", 4 ), TunnelType.FE_POWER );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_0", 5 ), TunnelType.FE_POWER );
|
||||
|
||||
/**
|
||||
* EU tunnel items
|
||||
*/
|
||||
|
||||
// FIXME this.addNewAttunement( this.getModItem( "ic2", "cable", 0 ), TunnelType.IC2_POWER ); // Copper cable
|
||||
// FIXME this.addNewAttunement( this.getModItem( "ic2", "cable", 1 ), TunnelType.IC2_POWER ); // Glass fibre cable
|
||||
// FIXME this.addNewAttunement( this.getModItem( "ic2", "cable", 2 ), TunnelType.IC2_POWER ); // Gold cable
|
||||
// FIXME this.addNewAttunement( this.getModItem( "ic2", "cable", 3 ), TunnelType.IC2_POWER ); // HV cable
|
||||
// FIXME this.addNewAttunement( this.getModItem( "ic2", "cable", 4 ), TunnelType.IC2_POWER ); // Tin cable
|
||||
|
||||
/**
|
||||
* attune based on most redstone base items.
|
||||
*/
|
||||
@@ -114,16 +88,6 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry {
|
||||
this.addNewAttunement(new ItemStack(Blocks.HOPPER), TunnelType.ITEM);
|
||||
this.addNewAttunement(new ItemStack(Blocks.CHEST), TunnelType.ITEM);
|
||||
this.addNewAttunement(new ItemStack(Blocks.TRAPPED_CHEST), TunnelType.ITEM);
|
||||
// FIXME this.addNewAttunement( this.getModItem( "extrautilities", "extractor_base", 0 ), TunnelType.ITEM );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "mekanism", "parttransmitter", 9 ), TunnelType.ITEM );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 0 ), TunnelType.ITEM ); // itemduct
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 1 ), TunnelType.ITEM ); // itemduct
|
||||
// FIXME // (opaque)
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 2 ), TunnelType.ITEM ); // impulse
|
||||
// FIXME // itemduct
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 3 ), TunnelType.ITEM ); // impulse
|
||||
// FIXME // itemduct
|
||||
// (opaque)
|
||||
|
||||
/**
|
||||
* attune based on lots of random item related stuff
|
||||
@@ -132,18 +96,7 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry {
|
||||
this.addNewAttunement(new ItemStack(Items.LAVA_BUCKET), TunnelType.FLUID);
|
||||
this.addNewAttunement(new ItemStack(Items.MILK_BUCKET), TunnelType.FLUID);
|
||||
this.addNewAttunement(new ItemStack(Items.WATER_BUCKET), TunnelType.FLUID);
|
||||
// FIXME this.addNewAttunement( this.getModItem( "mekanism", "machineblock2", 11 ), TunnelType.FLUID );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "mekanism", "parttransmitter", 4 ), TunnelType.FLUID );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "extrautilities", "extractor_base", 6 ), TunnelType.FLUID );
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 0 ), TunnelType.FLUID ); // fluiduct
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 1 ), TunnelType.FLUID ); // fluiduct
|
||||
// FIXME // (opaque)
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 2 ), TunnelType.FLUID ); // fluiduct
|
||||
// FIXME // hardened
|
||||
// FIXME this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 3 ), TunnelType.FLUID ); // fluiduct
|
||||
// FIXME // hardened
|
||||
// FIXME // (opaque)
|
||||
// FIXME
|
||||
|
||||
for (final AEColor c : AEColor.values()) {
|
||||
this.addNewAttunement(parts.cableGlass().stack(c, 1), TunnelType.ME);
|
||||
this.addNewAttunement(parts.cableCovered().stack(c, 1), TunnelType.ME);
|
||||
@@ -154,30 +107,11 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry {
|
||||
/**
|
||||
* attune based caps
|
||||
*/
|
||||
// FIXME FABRIC this.addNewAttunement(Capabilities.FORGE_ENERGY,
|
||||
// TunnelType.FE_POWER);
|
||||
this.addNewAttunement(FluidAttributes.EXTRACTABLE, TunnelType.FLUID);
|
||||
this.addNewAttunement(FluidAttributes.INSERTABLE, TunnelType.FLUID);
|
||||
this.addNewAttunement(FluidAttributes.FIXED_INV, TunnelType.FLUID);
|
||||
this.addNewAttunement(FluidAttributes.GROUPED_INV, TunnelType.FLUID);
|
||||
|
||||
/**
|
||||
* attune based on the ItemStack's modId
|
||||
*/
|
||||
|
||||
this.addNewAttunement("thermaldynamics", TunnelType.FE_POWER);
|
||||
this.addNewAttunement("thermalexpansion", TunnelType.FE_POWER);
|
||||
this.addNewAttunement("thermalfoundation", TunnelType.FE_POWER);
|
||||
// TODO: Remove when confirmed that the official 1.12 version of EnderIO will
|
||||
// support FE.
|
||||
this.addNewAttunement("enderio", TunnelType.FE_POWER);
|
||||
// TODO: Remove when confirmed that the official 1.12 version of Mekanism will
|
||||
// support FE.
|
||||
this.addNewAttunement("mekanism", TunnelType.FE_POWER);
|
||||
// TODO: Remove when support for RFTools' Powercells support is added
|
||||
this.addNewAttunement("rftools", TunnelType.FE_POWER);
|
||||
this.addNewAttunement("ic2", TunnelType.IC2_POWER);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,7 +25,6 @@ import appeng.api.features.IP2PTunnelRegistry;
|
||||
import appeng.api.features.IPlayerRegistry;
|
||||
import appeng.api.features.IRegistryContainer;
|
||||
import appeng.api.features.IWirelessTermRegistry;
|
||||
import appeng.api.features.IWorldGen;
|
||||
import appeng.api.movable.IMovableRegistry;
|
||||
import appeng.api.networking.IGridCacheRegistry;
|
||||
import appeng.api.parts.IPartModels;
|
||||
@@ -99,11 +98,6 @@ public class RegistryContainer implements IRegistryContainer {
|
||||
return this.playerRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldGen worldgen() {
|
||||
return WorldGenRegistry.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModels partModels() {
|
||||
return this.partModels;
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.core.features.registries;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.features.IWorldGen;
|
||||
|
||||
public final class WorldGenRegistry implements IWorldGen {
|
||||
|
||||
public static final WorldGenRegistry INSTANCE = new WorldGenRegistry();
|
||||
private final TypeSet[] types;
|
||||
|
||||
private WorldGenRegistry() {
|
||||
|
||||
this.types = new TypeSet[WorldGenType.values().length];
|
||||
|
||||
for (final WorldGenType type : WorldGenType.values()) {
|
||||
this.types[type.ordinal()] = new TypeSet();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableWorldGenForDimension(final WorldGenType type, final Identifier dimensionID) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Bad Type Passed");
|
||||
}
|
||||
|
||||
this.types[type.ordinal()].enabledDimensions.add(dimensionID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableWorldGenForDimension(final WorldGenType type, final Identifier dimensionID) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Bad Type Passed");
|
||||
}
|
||||
|
||||
this.types[type.ordinal()].badDimensions.add(dimensionID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWorldGenEnabled(final WorldGenType type, final ServerWorld w) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Bad Type Passed");
|
||||
}
|
||||
|
||||
if (w == null) {
|
||||
throw new IllegalArgumentException("Bad Provider Passed");
|
||||
}
|
||||
|
||||
Identifier id = w.getRegistryKey().getValue();
|
||||
final boolean isBadDimension = this.types[type.ordinal()].badDimensions.contains(id);
|
||||
final boolean isGoodDimension = this.types[type.ordinal()].enabledDimensions.contains(id);
|
||||
|
||||
if (isBadDimension) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isGoodDimension && type == WorldGenType.METEORITES) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class TypeSet {
|
||||
final HashSet<Identifier> badDimensions = new HashSet<>();
|
||||
final HashSet<Identifier> enabledDimensions = new HashSet<>();
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import appeng.core.sync.packets.BlockTransitionEffectPacket;
|
||||
import appeng.core.sync.packets.ClickPacket;
|
||||
import appeng.core.sync.packets.CompassRequestPacket;
|
||||
import appeng.core.sync.packets.CompassResponsePacket;
|
||||
import appeng.core.sync.packets.CompressedNBTPacket;
|
||||
import appeng.core.sync.packets.ConfigButtonPacket;
|
||||
import appeng.core.sync.packets.ConfigValuePacket;
|
||||
import appeng.core.sync.packets.CraftRequestPacket;
|
||||
@@ -39,6 +38,7 @@ import appeng.core.sync.packets.ItemTransitionEffectPacket;
|
||||
import appeng.core.sync.packets.JEIRecipePacket;
|
||||
import appeng.core.sync.packets.LightningPacket;
|
||||
import appeng.core.sync.packets.MEFluidInventoryUpdatePacket;
|
||||
import appeng.core.sync.packets.MEInterfaceUpdatePacket;
|
||||
import appeng.core.sync.packets.MEInventoryUpdatePacket;
|
||||
import appeng.core.sync.packets.MatterCannonPacket;
|
||||
import appeng.core.sync.packets.PaintedEntityPacket;
|
||||
@@ -99,7 +99,7 @@ public class BasePacketHandler {
|
||||
|
||||
PACKET_ASSEMBLER_ANIMATION(AssemblerAnimationPacket.class, AssemblerAnimationPacket::new),
|
||||
|
||||
PACKET_COMPRESSED_NBT(CompressedNBTPacket.class, CompressedNBTPacket::new),
|
||||
PACKET_ME_INTERFACE_UPDATE(MEInterfaceUpdatePacket.class, MEInterfaceUpdatePacket::new),
|
||||
|
||||
PACKET_PAINTED_ENTITY(PaintedEntityPacket.class, PaintedEntityPacket::new),
|
||||
|
||||
|
||||
@@ -18,15 +18,26 @@
|
||||
|
||||
package appeng.core.sync.packets;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.ShapedRecipe;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
@@ -41,11 +52,14 @@ import appeng.api.networking.storage.IStorageGrid;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.container.implementations.PatternTermContainer;
|
||||
import appeng.core.Api;
|
||||
import appeng.core.sync.BasePacket;
|
||||
import appeng.core.sync.BasePacketHandler;
|
||||
import appeng.core.sync.network.INetworkInfo;
|
||||
import appeng.helpers.IContainerCraftingPacket;
|
||||
import appeng.items.storage.ViewCellItem;
|
||||
import appeng.mixins.IngredientAccessor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.AdaptorFixedInv;
|
||||
@@ -55,151 +69,303 @@ import appeng.util.prioritylist.IPartitionList;
|
||||
|
||||
public class JEIRecipePacket extends BasePacket {
|
||||
|
||||
private ItemStack[][] recipe;
|
||||
/**
|
||||
* Transmit only a recipe ID.
|
||||
*/
|
||||
private static final int INLINE_RECIPE_NONE = 1;
|
||||
|
||||
/**
|
||||
* Transmit the information about the recipe we actually need. This is
|
||||
* explicitly limited since this is untrusted client->server info.
|
||||
*/
|
||||
private static final int INLINE_RECIPE_SHAPED = 2;
|
||||
|
||||
private Identifier recipeId;
|
||||
/**
|
||||
* This is optional, in case the client already knows it could not resolve the
|
||||
* recipe id.
|
||||
*/
|
||||
@Nullable
|
||||
private Recipe<?> recipe;
|
||||
private boolean crafting;
|
||||
|
||||
public JEIRecipePacket(final PacketByteBuf stream) {
|
||||
final CompoundTag comp = stream.readCompoundTag();
|
||||
if (comp != null) {
|
||||
this.recipe = new ItemStack[9][];
|
||||
for (int x = 0; x < this.recipe.length; x++) {
|
||||
final ListTag list = comp.getList("#" + x, 10);
|
||||
if (list.size() > 0) {
|
||||
this.recipe[x] = new ItemStack[list.size()];
|
||||
for (int y = 0; y < list.size(); y++) {
|
||||
this.recipe[x][y] = ItemStack.fromTag(list.getCompound(y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.crafting = stream.readBoolean();
|
||||
final String id = stream.readString(Short.MAX_VALUE);
|
||||
this.recipeId = new Identifier(id);
|
||||
|
||||
// api
|
||||
public JEIRecipePacket(final CompoundTag recipe) {
|
||||
final PacketByteBuf data = new PacketByteBuf(Unpooled.buffer());
|
||||
|
||||
data.writeInt(this.getPacketID());
|
||||
|
||||
data.writeCompoundTag(recipe);
|
||||
|
||||
this.configureWrite(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serverPacketData(final INetworkInfo manager, final PlayerEntity player) {
|
||||
final ServerPlayerEntity pmp = (ServerPlayerEntity) player;
|
||||
final ScreenHandler con = pmp.currentScreenHandler;
|
||||
|
||||
if (!(con instanceof IContainerCraftingPacket)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final IContainerCraftingPacket cct = (IContainerCraftingPacket) con;
|
||||
final IGridNode node = cct.getNetworkNode();
|
||||
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final IGrid grid = node.getGrid();
|
||||
if (grid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final IStorageGrid inv = grid.getCache(IStorageGrid.class);
|
||||
final IEnergyGrid energy = grid.getCache(IEnergyGrid.class);
|
||||
final ISecurityGrid security = grid.getCache(ISecurityGrid.class);
|
||||
final ICraftingGrid crafting = grid.getCache(ICraftingGrid.class);
|
||||
final FixedItemInv craftMatrix = cct.getInventoryByName("crafting");
|
||||
final FixedItemInv playerInventory = cct.getInventoryByName("player");
|
||||
|
||||
if (inv != null && this.recipe != null && security != null) {
|
||||
final IMEMonitor<IAEItemStack> storage = inv
|
||||
.getInventory(Api.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
final IPartitionList<IAEItemStack> filter = ViewCellItem.createFilter(cct.getViewCells());
|
||||
|
||||
for (int x = 0; x < craftMatrix.getSlotCount(); x++) {
|
||||
ItemStack currentItem = craftMatrix.getInvStack(x);
|
||||
|
||||
// prepare slots
|
||||
if (!currentItem.isEmpty()) {
|
||||
// already the correct item?
|
||||
ItemStack newItem = this.canUseInSlot(x, currentItem);
|
||||
|
||||
// put away old item
|
||||
if (newItem != currentItem && security.hasPermission(player, SecurityPermissions.INJECT)) {
|
||||
final IAEItemStack in = AEItemStack.fromItemStack(currentItem);
|
||||
final IAEItemStack out = cct.useRealItems()
|
||||
? Platform.poweredInsert(energy, storage, in, cct.getActionSource())
|
||||
: null;
|
||||
if (out != null) {
|
||||
currentItem = out.createItemStack();
|
||||
} else {
|
||||
currentItem = ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentItem.isEmpty() && this.recipe[x] != null) {
|
||||
// for each variant
|
||||
for (int y = 0; y < this.recipe[x].length && currentItem.isEmpty(); y++) {
|
||||
final IAEItemStack request = AEItemStack.fromItemStack(this.recipe[x][y]);
|
||||
if (request != null) {
|
||||
// try ae
|
||||
if ((filter == null || filter.isListed(request))
|
||||
&& security.hasPermission(player, SecurityPermissions.EXTRACT)) {
|
||||
request.setStackSize(1);
|
||||
IAEItemStack out;
|
||||
|
||||
if (cct.useRealItems()) {
|
||||
out = Platform.poweredExtraction(energy, storage, request, cct.getActionSource());
|
||||
} else {
|
||||
// Query the crafting grid if there is a pattern providing the item
|
||||
if (!crafting.getCraftingFor(request, null, 0, null).isEmpty()) {
|
||||
out = request;
|
||||
} else {
|
||||
// Fall back using an existing item
|
||||
out = storage.extractItems(request, Actionable.SIMULATE, cct.getActionSource());
|
||||
}
|
||||
}
|
||||
|
||||
if (out != null) {
|
||||
currentItem = out.createItemStack();
|
||||
}
|
||||
}
|
||||
|
||||
// try inventory
|
||||
if (currentItem.isEmpty()) {
|
||||
AdaptorFixedInv ad = new AdaptorFixedInv(playerInventory);
|
||||
|
||||
if (cct.useRealItems()) {
|
||||
currentItem = ad.removeItems(1, this.recipe[x][y], null);
|
||||
} else {
|
||||
currentItem = ad.simulateRemove(1, this.recipe[x][y], null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemHandlerUtil.setStackInSlot(craftMatrix, x, currentItem);
|
||||
}
|
||||
con.onContentChanged(new WrapperInvItemHandler(craftMatrix));
|
||||
int inlineRecipeType = stream.readVarInt();
|
||||
switch (inlineRecipeType) {
|
||||
case INLINE_RECIPE_NONE:
|
||||
break;
|
||||
case INLINE_RECIPE_SHAPED:
|
||||
recipe = RecipeSerializer.SHAPED.read(this.recipeId, stream);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid inline recipe type.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param slot
|
||||
* @param is itemstack
|
||||
* @return is if it can be used, else EMPTY
|
||||
* Sends a recipe identified by the given recipe ID to the server for either
|
||||
* filling a crafting grid or a pattern.
|
||||
*/
|
||||
private ItemStack canUseInSlot(int slot, ItemStack is) {
|
||||
if (this.recipe[slot] != null) {
|
||||
for (ItemStack option : this.recipe[slot]) {
|
||||
if (is.isItemEqual(option)) {
|
||||
return is;
|
||||
public JEIRecipePacket(final Identifier recipeId, final boolean crafting) {
|
||||
PacketByteBuf data = createCommonHeader(recipeId, crafting, INLINE_RECIPE_NONE);
|
||||
this.configureWrite(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a recipe to the server for either filling a crafting grid or a pattern.
|
||||
* <p>
|
||||
* Prefer the id-based constructor above whereever possible.
|
||||
*/
|
||||
public JEIRecipePacket(final ShapedRecipe recipe, final boolean crafting) {
|
||||
PacketByteBuf data = createCommonHeader(recipe.getId(), crafting, INLINE_RECIPE_SHAPED);
|
||||
RecipeSerializer.SHAPED.write(data, recipe);
|
||||
this.configureWrite(data);
|
||||
}
|
||||
|
||||
private PacketByteBuf createCommonHeader(Identifier recipeId, boolean crafting, int inlineRecipeType) {
|
||||
final PacketByteBuf data = new PacketByteBuf(Unpooled.buffer());
|
||||
|
||||
data.writeInt(this.getPacketID());
|
||||
data.writeBoolean(crafting);
|
||||
data.writeIdentifier(recipeId);
|
||||
data.writeVarInt(inlineRecipeType);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Servside handler for this packet.
|
||||
* <p>
|
||||
* Makes use of {@link Preconditions#checkArgument(boolean)} as the
|
||||
* {@link BasePacketHandler} is catching them and in general these cases should
|
||||
* never happen except in an error case and should be logged then.
|
||||
*/
|
||||
@Override
|
||||
public void serverPacketData(final INetworkInfo manager, final PlayerEntity player) {
|
||||
// Setup and verification
|
||||
final ServerPlayerEntity pmp = (ServerPlayerEntity) player;
|
||||
final ScreenHandler con = pmp.currentScreenHandler;
|
||||
Preconditions.checkArgument(con instanceof IContainerCraftingPacket);
|
||||
|
||||
Recipe<?> recipe = player.getEntityWorld().getRecipeManager().get(this.recipeId).orElse(null);
|
||||
if (recipe == null && this.recipe != null) {
|
||||
// Certain recipes (i.e. AE2 facades) are represented in JEI as ShapedRecipe's,
|
||||
// while in reality they
|
||||
// are special recipes. Those recipes are sent across the wire...
|
||||
recipe = this.recipe;
|
||||
}
|
||||
Preconditions.checkArgument(recipe != null);
|
||||
|
||||
final IContainerCraftingPacket cct = (IContainerCraftingPacket) con;
|
||||
final IGridNode node = cct.getNetworkNode();
|
||||
|
||||
Preconditions.checkArgument(node != null);
|
||||
|
||||
final IGrid grid = node.getGrid();
|
||||
Preconditions.checkArgument(grid != null);
|
||||
|
||||
final IStorageGrid inv = grid.getCache(IStorageGrid.class);
|
||||
Preconditions.checkArgument(inv != null);
|
||||
|
||||
final ISecurityGrid security = grid.getCache(ISecurityGrid.class);
|
||||
Preconditions.checkArgument(security != null);
|
||||
|
||||
final IEnergyGrid energy = grid.getCache(IEnergyGrid.class);
|
||||
final ICraftingGrid crafting = grid.getCache(ICraftingGrid.class);
|
||||
final FixedItemInv craftMatrix = cct.getInventoryByName("crafting");
|
||||
final FixedItemInv playerInventory = cct.getInventoryByName("player");
|
||||
|
||||
final IMEMonitor<IAEItemStack> storage = inv
|
||||
.getInventory(Api.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
final IPartitionList<IAEItemStack> filter = ViewCellItem.createFilter(cct.getViewCells());
|
||||
final DefaultedList<Ingredient> ingredients = this.ensure3by3CraftingMatrix(recipe);
|
||||
|
||||
// Handle each slot
|
||||
for (int x = 0; x < craftMatrix.getSlotCount(); x++) {
|
||||
ItemStack currentItem = craftMatrix.getInvStack(x);
|
||||
Ingredient ingredient = ingredients.get(x);
|
||||
|
||||
// prepare slots
|
||||
if (!currentItem.isEmpty()) {
|
||||
// already the correct item? True, skip everything else
|
||||
ItemStack newItem = this.canUseInSlot(ingredient, currentItem);
|
||||
|
||||
// put away old item, if not correct
|
||||
if (newItem != currentItem && security.hasPermission(player, SecurityPermissions.INJECT)) {
|
||||
final IAEItemStack in = AEItemStack.fromItemStack(currentItem);
|
||||
final IAEItemStack out = cct.useRealItems()
|
||||
? Platform.poweredInsert(energy, storage, in, cct.getActionSource())
|
||||
: null;
|
||||
if (out != null) {
|
||||
currentItem = out.createItemStack();
|
||||
} else {
|
||||
currentItem = ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find item or pattern from the network
|
||||
if (currentItem.isEmpty() && security.hasPermission(player, SecurityPermissions.EXTRACT)) {
|
||||
IAEItemStack out;
|
||||
|
||||
if (cct.useRealItems()) {
|
||||
IAEItemStack request = findBestMatchingItemStack(ingredient, filter, storage, cct);
|
||||
out = request != null
|
||||
? Platform.poweredExtraction(energy, storage, request.setStackSize(1),
|
||||
cct.getActionSource())
|
||||
: null;
|
||||
} else {
|
||||
out = findBestMatchingPattern(ingredient, filter, crafting, storage, cct);
|
||||
if (out == null) {
|
||||
out = findBestMatchingItemStack(ingredient, filter, storage, cct);
|
||||
}
|
||||
if (out == null && getMatchingStacks(ingredient).length > 0) {
|
||||
out = AEItemStack.fromItemStack(getMatchingStacks(ingredient)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (out != null) {
|
||||
currentItem = out.createItemStack();
|
||||
}
|
||||
}
|
||||
|
||||
// If still nothing, search the player inventory.
|
||||
if (currentItem.isEmpty()) {
|
||||
ItemStack[] matchingStacks = getMatchingStacks(ingredient);
|
||||
for (ItemStack matchingStack : matchingStacks) {
|
||||
if (currentItem.isEmpty()) {
|
||||
AdaptorFixedInv ad = new AdaptorFixedInv(playerInventory);
|
||||
|
||||
if (cct.useRealItems()) {
|
||||
currentItem = ad.removeItems(1, matchingStack, null);
|
||||
} else {
|
||||
currentItem = ad.simulateRemove(1, matchingStack, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemHandlerUtil.setStackInSlot(craftMatrix, x, currentItem);
|
||||
}
|
||||
|
||||
if (!this.crafting) {
|
||||
this.handleProcessing(con, cct, recipe);
|
||||
}
|
||||
|
||||
con.onContentChanged(new WrapperInvItemHandler(craftMatrix));
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private static ItemStack[] getMatchingStacks(Ingredient ingredient) {
|
||||
IngredientAccessor accessor = (IngredientAccessor) (Object) ingredient;
|
||||
accessor.appeng_cacheMatchingStacks();
|
||||
if (ingredient.isEmpty()) {
|
||||
return new ItemStack[0];
|
||||
}
|
||||
ItemStack[] stacks = accessor.getMatchingStacks();
|
||||
if (stacks.length == 1 && stacks[0].isEmpty()) {
|
||||
return new ItemStack[0];
|
||||
}
|
||||
return stacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand any recipe to a 3x3 matrix.
|
||||
* <p>
|
||||
* Will throw an {@link IllegalArgumentException} in case it has more than 9 or
|
||||
* a shaped recipe is either wider or higher than 3. ingredients.
|
||||
*/
|
||||
private DefaultedList<Ingredient> ensure3by3CraftingMatrix(Recipe<?> recipe) {
|
||||
DefaultedList<Ingredient> ingredients = recipe.getPreviewInputs();
|
||||
DefaultedList<Ingredient> expandedIngredients = DefaultedList.ofSize(9, Ingredient.EMPTY);
|
||||
|
||||
Preconditions.checkArgument(ingredients.size() <= 9);
|
||||
|
||||
// shaped recipes can be smaller than 3x3, expand to 3x3 to match the crafting
|
||||
// matrix
|
||||
if (recipe instanceof ShapedRecipe) {
|
||||
ShapedRecipe shapedRecipe = (ShapedRecipe) recipe;
|
||||
int width = shapedRecipe.getWidth();
|
||||
int height = shapedRecipe.getHeight();
|
||||
Preconditions.checkArgument(width <= 3 && height <= 3);
|
||||
|
||||
for (int h = 0; h < height; h++) {
|
||||
for (int w = 0; w < width; w++) {
|
||||
int source = w + h * width;
|
||||
int target = w + h * 3;
|
||||
Ingredient i = ingredients.get(source);
|
||||
expandedIngredients.set(target, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
// Anything else should be a flat list
|
||||
else {
|
||||
for (int i = 0; i < ingredients.size(); i++) {
|
||||
expandedIngredients.set(i, ingredients.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return expandedIngredients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param is itemstack
|
||||
* @return is if it can be used, else EMPTY
|
||||
*/
|
||||
private ItemStack canUseInSlot(Ingredient ingredient, ItemStack is) {
|
||||
return Arrays.stream(getMatchingStacks(ingredient)).filter(p -> p.isItemEqual(is)).findFirst()
|
||||
.orElse(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first matching itemstack with the highest stored amount.
|
||||
*/
|
||||
private IAEItemStack findBestMatchingItemStack(Ingredient ingredients, IPartitionList<IAEItemStack> filter,
|
||||
IMEMonitor<IAEItemStack> storage, IContainerCraftingPacket cct) {
|
||||
return Arrays.stream(getMatchingStacks(ingredients)).map(AEItemStack::fromItemStack) //
|
||||
.filter(r -> r != null && (filter == null || filter.isListed(r))) //
|
||||
.map(s -> {
|
||||
// Determine the stored count
|
||||
IAEItemStack stored = storage.extractItems(s.copy().setStackSize(Long.MAX_VALUE),
|
||||
Actionable.SIMULATE, cct.getActionSource());
|
||||
return Pair.of(s, stored != null ? stored.getStackSize() : 0);
|
||||
}).min((left, right) -> Long.compare(right.getSecond(), left.getSecond()))//
|
||||
.map(Pair::getFirst).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This tries to find the first pattern matching the list of ingredients.
|
||||
* <p>
|
||||
* As additional condition, it sorts by the stored amount to return the one with
|
||||
* the highest stored amount.
|
||||
*/
|
||||
private IAEItemStack findBestMatchingPattern(Ingredient ingredients, IPartitionList<IAEItemStack> filter,
|
||||
ICraftingGrid crafting, IMEMonitor<IAEItemStack> storage, IContainerCraftingPacket cct) {
|
||||
return Arrays.stream(getMatchingStacks(ingredients)).map(AEItemStack::fromItemStack)
|
||||
.filter(r -> r != null && (filter == null || filter.isListed(r)))
|
||||
.map(s -> s.setCraftable(!crafting.getCraftingFor(s, null, 0, null).isEmpty()))
|
||||
.filter(IAEItemStack::isCraftable).map(s -> {
|
||||
final IAEItemStack stored = storage.extractItems(s, Actionable.SIMULATE, cct.getActionSource());
|
||||
return s.setStackSize(stored != null ? stored.getStackSize() : 0);
|
||||
}).min((left, right) -> {
|
||||
final int craftable = Boolean.compare(left.isCraftable(), right.isCraftable());
|
||||
return craftable != 0 ? craftable : Long.compare(right.getStackSize(), left.getStackSize());
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
private void handleProcessing(ScreenHandler con, IContainerCraftingPacket cct, Recipe<?> recipe) {
|
||||
if (con instanceof PatternTermContainer) {
|
||||
PatternTermContainer patternTerm = (PatternTermContainer) con;
|
||||
if (!patternTerm.craftingMode) {
|
||||
final FixedItemInv output = cct.getInventoryByName("output");
|
||||
ItemHandlerUtil.setStackInSlot(output, 0, recipe.getOutput());
|
||||
ItemHandlerUtil.setStackInSlot(output, 1, ItemStack.EMPTY);
|
||||
ItemHandlerUtil.setStackInSlot(output, 2, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,13 +19,9 @@
|
||||
package appeng.core.sync.packets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -41,7 +37,6 @@ import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.sync.BasePacket;
|
||||
import appeng.core.sync.network.INetworkInfo;
|
||||
import appeng.fluids.client.gui.FluidTerminalScreen;
|
||||
@@ -55,8 +50,6 @@ import appeng.fluids.util.AEFluidStack;
|
||||
public class MEFluidInventoryUpdatePacket extends BasePacket {
|
||||
private static final int UNCOMPRESSED_PACKET_BYTE_LIMIT = 16 * 1024 * 1024;
|
||||
private static final int OPERATION_BYTE_LIMIT = 2 * 1024;
|
||||
private static final int TEMP_BUFFER_SIZE = 1024;
|
||||
private static final int STREAM_MASK = 0xff;
|
||||
|
||||
// input.
|
||||
@Nullable
|
||||
@@ -66,47 +59,18 @@ public class MEFluidInventoryUpdatePacket extends BasePacket {
|
||||
|
||||
@Nullable
|
||||
private final PacketByteBuf data;
|
||||
@Nullable
|
||||
private final GZIPOutputStream compressFrame;
|
||||
|
||||
private int writtenBytes = 0;
|
||||
private boolean empty = true;
|
||||
|
||||
public MEFluidInventoryUpdatePacket(final PacketByteBuf stream) {
|
||||
this.data = null;
|
||||
this.compressFrame = null;
|
||||
this.list = new LinkedList<>();
|
||||
this.ref = stream.readByte();
|
||||
|
||||
try (final GZIPInputStream gzReader = new GZIPInputStream(new InputStream() {
|
||||
@Override
|
||||
public int read() {
|
||||
if (stream.readableBytes() <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return stream.readByte() & STREAM_MASK;
|
||||
}
|
||||
})) {
|
||||
|
||||
final PacketByteBuf uncompressed = new PacketByteBuf(Unpooled.buffer(stream.readableBytes()));
|
||||
final byte[] tmp = new byte[TEMP_BUFFER_SIZE];
|
||||
|
||||
while (gzReader.available() != 0) {
|
||||
final int bytes = gzReader.read(tmp);
|
||||
|
||||
if (bytes > 0) {
|
||||
uncompressed.writeBytes(tmp, 0, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
while (uncompressed.readableBytes() > 0) {
|
||||
this.list.add(AEFluidStack.fromPacket(uncompressed));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to decompress packet.", e);
|
||||
while (stream.readableBytes() > 0) {
|
||||
this.list.add(AEFluidStack.fromPacket(stream));
|
||||
}
|
||||
|
||||
this.empty = this.list.isEmpty();
|
||||
}
|
||||
|
||||
@@ -121,14 +85,6 @@ public class MEFluidInventoryUpdatePacket extends BasePacket {
|
||||
this.data = new PacketByteBuf(Unpooled.buffer(OPERATION_BYTE_LIMIT));
|
||||
this.data.writeInt(this.getPacketID());
|
||||
this.data.writeByte(this.ref);
|
||||
|
||||
this.compressFrame = new GZIPOutputStream(new OutputStream() {
|
||||
@Override
|
||||
public void write(final int value) {
|
||||
MEFluidInventoryUpdatePacket.this.data.writeByte(value);
|
||||
}
|
||||
});
|
||||
|
||||
this.list = null;
|
||||
}
|
||||
|
||||
@@ -145,28 +101,19 @@ public class MEFluidInventoryUpdatePacket extends BasePacket {
|
||||
@Nullable
|
||||
@Override
|
||||
public Packet<?> toPacket(NetworkSide direction) {
|
||||
try {
|
||||
this.compressFrame.close();
|
||||
|
||||
this.configureWrite(this.data);
|
||||
return super.toPacket(direction);
|
||||
} catch (final IOException e) {
|
||||
AELog.debug(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
this.configureWrite(this.data);
|
||||
return super.toPacket(direction);
|
||||
}
|
||||
|
||||
public void appendFluid(final IAEFluidStack fs) throws IOException, BufferOverflowException {
|
||||
final PacketByteBuf tmp = new PacketByteBuf(Unpooled.buffer(OPERATION_BYTE_LIMIT));
|
||||
fs.writeToPacket(tmp);
|
||||
|
||||
this.compressFrame.flush();
|
||||
if (this.writtenBytes + tmp.readableBytes() > UNCOMPRESSED_PACKET_BYTE_LIMIT) {
|
||||
throw new BufferOverflowException();
|
||||
} else {
|
||||
this.writtenBytes += tmp.readableBytes();
|
||||
this.compressFrame.write(tmp.array(), 0, tmp.readableBytes());
|
||||
this.data.writeBytes(tmp.array(), 0, tmp.readableBytes());
|
||||
this.empty = false;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-44
@@ -18,13 +18,7 @@
|
||||
|
||||
package appeng.core.sync.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
@@ -34,62 +28,30 @@ import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import appeng.client.gui.implementations.InterfaceTerminalScreen;
|
||||
import appeng.core.sync.BasePacket;
|
||||
import appeng.core.sync.network.INetworkInfo;
|
||||
|
||||
//TODO, this is pointless, NBT is already compressed when written to a PacketBuffer.
|
||||
public class CompressedNBTPacket extends BasePacket {
|
||||
public class MEInterfaceUpdatePacket extends BasePacket {
|
||||
|
||||
// input.
|
||||
private final CompoundTag in;
|
||||
// output...
|
||||
private final PacketByteBuf data;
|
||||
private final GZIPOutputStream compressFrame;
|
||||
|
||||
public CompressedNBTPacket(final PacketByteBuf stream) {
|
||||
public MEInterfaceUpdatePacket(final PacketByteBuf stream) {
|
||||
this.data = null;
|
||||
this.compressFrame = null;
|
||||
|
||||
try (DataInputStream inStream = new DataInputStream(new GZIPInputStream(new InputStream() {
|
||||
|
||||
@Override
|
||||
public int read() {
|
||||
if (stream.readableBytes() <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return stream.readByte() & 0xff;
|
||||
}
|
||||
}))) {
|
||||
this.in = NbtIo.read(inStream);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to decompress packet.", e);
|
||||
}
|
||||
this.in = stream.readCompoundTag();
|
||||
}
|
||||
|
||||
// api
|
||||
public CompressedNBTPacket(final CompoundTag din) throws IOException {
|
||||
|
||||
public MEInterfaceUpdatePacket(final CompoundTag din) throws IOException {
|
||||
this.in = null;
|
||||
this.data = new PacketByteBuf(Unpooled.buffer(2048));
|
||||
this.data.writeInt(this.getPacketID());
|
||||
|
||||
this.in = din;
|
||||
|
||||
this.compressFrame = new GZIPOutputStream(new OutputStream() {
|
||||
|
||||
@Override
|
||||
public void write(final int value) {
|
||||
CompressedNBTPacket.this.data.writeByte(value);
|
||||
}
|
||||
});
|
||||
|
||||
NbtIo.write(din, new DataOutputStream(this.compressFrame));
|
||||
this.compressFrame.close();
|
||||
|
||||
this.data.writeCompoundTag(din);
|
||||
this.configureWrite(this.data);
|
||||
}
|
||||
|
||||
@@ -19,13 +19,9 @@
|
||||
package appeng.core.sync.packets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -45,7 +41,6 @@ import appeng.client.gui.implementations.CraftConfirmScreen;
|
||||
import appeng.client.gui.implementations.CraftingCPUScreen;
|
||||
import appeng.client.gui.implementations.MEMonitorableScreen;
|
||||
import appeng.client.gui.implementations.NetworkStatusScreen;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.sync.BasePacket;
|
||||
import appeng.core.sync.network.INetworkInfo;
|
||||
import appeng.util.item.AEItemStack;
|
||||
@@ -53,8 +48,6 @@ import appeng.util.item.AEItemStack;
|
||||
public class MEInventoryUpdatePacket extends BasePacket {
|
||||
private static final int UNCOMPRESSED_PACKET_BYTE_LIMIT = 16 * 1024 * 1024;
|
||||
private static final int OPERATION_BYTE_LIMIT = 2 * 1024;
|
||||
private static final int TEMP_BUFFER_SIZE = 1024;
|
||||
private static final int STREAM_MASK = 0xff;
|
||||
|
||||
// input.
|
||||
@Nullable
|
||||
@@ -64,48 +57,18 @@ public class MEInventoryUpdatePacket extends BasePacket {
|
||||
|
||||
@Nullable
|
||||
private final PacketByteBuf data;
|
||||
@Nullable
|
||||
private final GZIPOutputStream compressFrame;
|
||||
|
||||
private int writtenBytes = 0;
|
||||
private boolean empty = true;
|
||||
|
||||
public MEInventoryUpdatePacket(final PacketByteBuf stream) {
|
||||
this.data = null;
|
||||
this.compressFrame = null;
|
||||
this.list = new ArrayList<>();
|
||||
this.ref = stream.readByte();
|
||||
|
||||
// int originalBytes = stream.readableBytes();
|
||||
|
||||
try (GZIPInputStream gzReader = new GZIPInputStream(new InputStream() {
|
||||
@Override
|
||||
public int read() {
|
||||
if (stream.readableBytes() <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return stream.readByte() & STREAM_MASK;
|
||||
}
|
||||
})) {
|
||||
final PacketByteBuf uncompressed = new PacketByteBuf(Unpooled.buffer(stream.readableBytes()));
|
||||
final byte[] tmp = new byte[TEMP_BUFFER_SIZE];
|
||||
|
||||
while (gzReader.available() != 0) {
|
||||
final int bytes = gzReader.read(tmp);
|
||||
|
||||
if (bytes > 0) {
|
||||
uncompressed.writeBytes(tmp, 0, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
while (uncompressed.readableBytes() > 0) {
|
||||
this.list.add(AEItemStack.fromPacket(uncompressed));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to decompress packet.", e);
|
||||
while (stream.readableBytes() > 0) {
|
||||
this.list.add(AEItemStack.fromPacket(stream));
|
||||
}
|
||||
|
||||
this.empty = this.list.isEmpty();
|
||||
}
|
||||
|
||||
@@ -120,14 +83,6 @@ public class MEInventoryUpdatePacket extends BasePacket {
|
||||
this.data = new PacketByteBuf(Unpooled.buffer(OPERATION_BYTE_LIMIT));
|
||||
this.data.writeInt(this.getPacketID());
|
||||
this.data.writeByte(this.ref);
|
||||
|
||||
this.compressFrame = new GZIPOutputStream(new OutputStream() {
|
||||
@Override
|
||||
public void write(final int value) {
|
||||
MEInventoryUpdatePacket.this.data.writeByte(value);
|
||||
}
|
||||
});
|
||||
|
||||
this.list = null;
|
||||
}
|
||||
|
||||
@@ -156,28 +111,19 @@ public class MEInventoryUpdatePacket extends BasePacket {
|
||||
@Nullable
|
||||
@Override
|
||||
public Packet<?> toPacket(NetworkSide direction) {
|
||||
try {
|
||||
this.compressFrame.close();
|
||||
|
||||
this.configureWrite(this.data);
|
||||
return super.toPacket(direction);
|
||||
} catch (final IOException e) {
|
||||
AELog.debug(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
this.configureWrite(this.data);
|
||||
return super.toPacket(direction);
|
||||
}
|
||||
|
||||
public void appendItem(final IAEItemStack is) throws IOException, BufferOverflowException {
|
||||
final PacketByteBuf tmp = new PacketByteBuf(Unpooled.buffer(OPERATION_BYTE_LIMIT));
|
||||
is.writeToPacket(tmp);
|
||||
|
||||
this.compressFrame.flush();
|
||||
if (this.writtenBytes + tmp.readableBytes() > UNCOMPRESSED_PACKET_BYTE_LIMIT) {
|
||||
throw new BufferOverflowException();
|
||||
} else {
|
||||
this.writtenBytes += tmp.readableBytes();
|
||||
this.compressFrame.write(tmp.array(), 0, tmp.readableBytes());
|
||||
this.data.writeBytes(tmp.array(), 0, tmp.readableBytes());
|
||||
this.empty = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.helpers.AEMaterials;
|
||||
|
||||
public class QuartzGlassBlock extends AbstractGlassBlock {
|
||||
|
||||
public QuartzGlassBlock(Settings props) {
|
||||
@@ -33,8 +31,7 @@ public class QuartzGlassBlock extends AbstractGlassBlock {
|
||||
|
||||
@Override
|
||||
public boolean isSideInvisible(BlockState state, BlockState adjacentBlockState, Direction side) {
|
||||
final Material mat = adjacentBlockState.getMaterial();
|
||||
if (mat == Material.GLASS || mat == AEMaterials.GLASS) {
|
||||
if (adjacentBlockState.getBlock() instanceof QuartzGlassBlock) {
|
||||
if (adjacentBlockState.getRenderType() == state.getRenderType()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,6 @@ public abstract class AEBaseItemEntity extends ItemEntity implements ICustomEnti
|
||||
this.yaw = this.random.nextFloat() * 360.0F;
|
||||
this.setVelocity(this.random.nextDouble() * 0.2D - 0.1D, 0.2D, this.random.nextDouble() * 0.2D - 0.1D);
|
||||
this.setStack(stack);
|
||||
// FIXME FABRIC Needs replacement hook this.lifespan =
|
||||
// stack.getEntityLifespan(world);
|
||||
}
|
||||
|
||||
protected List<Entity> getCheckedEntitiesWithinAABBExcludingEntity(final Box region) {
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
package appeng.entity;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.features.AEFeature;
|
||||
@@ -35,12 +36,29 @@ import appeng.client.EffectType;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.misc.CrystalSeedItem;
|
||||
import appeng.util.Platform;
|
||||
import appeng.mixins.ItemEntityAccessor;
|
||||
|
||||
public final class GrowingCrystalEntity extends AEBaseItemEntity {
|
||||
public class GrowingCrystalEntity extends AEBaseItemEntity {
|
||||
|
||||
public static EntityType<GrowingCrystalEntity> TYPE;
|
||||
|
||||
// Growth tick progress per tick by number of adjacent accelerators
|
||||
// Expressed as 1/1000th of a growth tick, applied to progress_1000
|
||||
// each time this entity ticks.
|
||||
private static final int[] GROWTH_TICK_PROGRESS = { //
|
||||
1, // no accelerators
|
||||
40, // 1 accelerator
|
||||
92, // 2 accelerators
|
||||
159, // 3 accelerators
|
||||
247, // 4 accelerators
|
||||
361, // 5 accelerators
|
||||
509 // 6 accelerators
|
||||
};
|
||||
|
||||
/**
|
||||
* The accumulated progress towards a single growth tick of the crystal in
|
||||
* 1/1000th of a growth tick.
|
||||
*/
|
||||
private int progress_1000 = 0;
|
||||
|
||||
public GrowingCrystalEntity(EntityType<? extends GrowingCrystalEntity> type, World world) {
|
||||
@@ -49,135 +67,152 @@ public final class GrowingCrystalEntity extends AEBaseItemEntity {
|
||||
|
||||
public GrowingCrystalEntity(final World w, final double x, final double y, final double z, final ItemStack is) {
|
||||
super(TYPE, w, x, y, z, is);
|
||||
this.setCovetedItem();
|
||||
// FIXME FABRIC This does not actually fix despawning, we need to Mixin,
|
||||
// probably.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (!AEConfig.instance().isFeatureEnabled(AEFeature.IN_WORLD_PURIFICATION)) {
|
||||
return;
|
||||
// Prevent the entity from despawning
|
||||
ItemEntityAccessor accessor = (ItemEntityAccessor) this;
|
||||
if (!this.world.isClient && accessor.getAge() >= 1000) {
|
||||
accessor.setAge(0);
|
||||
}
|
||||
|
||||
super.tick();
|
||||
|
||||
final ItemStack is = this.getStack();
|
||||
final Item gc = is.getItem();
|
||||
|
||||
if (gc instanceof IGrowableCrystal) // if it changes this just stops being an issue...
|
||||
{
|
||||
final int j = MathHelper.floor(this.getX());
|
||||
final int i = MathHelper.floor((this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0D);
|
||||
final int k = MathHelper.floor(this.getZ());
|
||||
if (!(gc instanceof IGrowableCrystal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final BlockState state = this.world.getBlockState(new BlockPos(j, i, k));
|
||||
final Material mat = state.getMaterial();
|
||||
final IGrowableCrystal cry = (IGrowableCrystal) is.getItem();
|
||||
applyGrowthTick((IGrowableCrystal) gc, is);
|
||||
}
|
||||
|
||||
final float multiplier = cry.getMultiplier(state.getBlock(), mat);
|
||||
final int speed = (int) Math.max(1, this.getSpeed(j, i, k) * multiplier);
|
||||
private void applyGrowthTick(IGrowableCrystal cry, ItemStack is) {
|
||||
if (!AEConfig.instance().isFeatureEnabled(AEFeature.IN_WORLD_PURIFICATION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean isClient = Platform.isClient();
|
||||
final int x = MathHelper.floor(this.getX());
|
||||
final int y = MathHelper.floor((this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0D);
|
||||
final int z = MathHelper.floor(this.getZ());
|
||||
|
||||
if (mat.isLiquid()) {
|
||||
if (isClient) {
|
||||
this.progress_1000++;
|
||||
} else {
|
||||
this.progress_1000 += speed;
|
||||
}
|
||||
} else {
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
final BlockState state = this.world.getBlockState(pos);
|
||||
|
||||
final float multiplier = cry.getMultiplier(state, world, pos);
|
||||
|
||||
if (multiplier <= 0) {
|
||||
// Crystal is in unsuitable material, reset progress and quit
|
||||
this.progress_1000 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
final int progressPerTick = (int) Math.max(1, this.getSpeed(pos) * multiplier);
|
||||
|
||||
if (world.isClient()) {
|
||||
// On the client, we reuse the growth-tick-progress
|
||||
// as a tick-counter for particle effects
|
||||
int len = getTicksBetweenParticleEffects(progressPerTick);
|
||||
if (++this.progress_1000 >= len) {
|
||||
this.progress_1000 = 0;
|
||||
AppEng.instance().spawnEffect(EffectType.Vibrant, this.world, this.getX(), this.getY() + 0.2,
|
||||
this.getZ(), null);
|
||||
}
|
||||
} else {
|
||||
this.progress_1000 += progressPerTick;
|
||||
|
||||
if (isClient) {
|
||||
int len = 40;
|
||||
if (this.progress_1000 >= 1000) {
|
||||
// We need to copy the stack or the change detection will not work and not sync
|
||||
// this new stack to the client
|
||||
ItemStack newItem = is.copy();
|
||||
|
||||
if (speed > 2) {
|
||||
len = 20;
|
||||
}
|
||||
|
||||
if (speed > 90) {
|
||||
len = 15;
|
||||
}
|
||||
|
||||
if (speed > 150) {
|
||||
len = 10;
|
||||
}
|
||||
|
||||
if (speed > 240) {
|
||||
len = 7;
|
||||
}
|
||||
|
||||
if (speed > 360) {
|
||||
len = 3;
|
||||
}
|
||||
|
||||
if (speed > 500) {
|
||||
len = 1;
|
||||
}
|
||||
|
||||
if (this.progress_1000 >= len) {
|
||||
this.progress_1000 = 0;
|
||||
AppEng.instance().spawnEffect(EffectType.Vibrant, this.world, this.getX(), this.getY() + 0.2,
|
||||
this.getZ(), null);
|
||||
}
|
||||
} else {
|
||||
if (this.progress_1000 > 1000) {
|
||||
// If we did not use a while loop here, the fastest growth for a crystal
|
||||
// would be limited to a minimum of 30 seconds (based on 600 required growth
|
||||
// ticks).
|
||||
// Should a crystal decide to use a high multiplier for a certain material,
|
||||
// it should be possible to go faster.
|
||||
do {
|
||||
newItem = cry.triggerGrowth(newItem);
|
||||
this.progress_1000 -= 1000;
|
||||
// We need to copy the stack or the change detection will not work and not sync
|
||||
// this new stack to the client
|
||||
ItemStack newItem = cry.triggerGrowth(is.copy());
|
||||
this.setStack(newItem);
|
||||
}
|
||||
// We assume that if the item changes, the process is complete and we can break
|
||||
} while (this.progress_1000 >= 1000 && newItem.getItem() == is.getItem());
|
||||
|
||||
this.setStack(newItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getSpeed(final int x, final int y, final int z) {
|
||||
final int per = 80;
|
||||
final float mul = 0.3f;
|
||||
|
||||
int qty = 0;
|
||||
|
||||
if (this.isAccelerated(x + 1, y, z)) {
|
||||
qty += per + qty * mul;
|
||||
private static int getTicksBetweenParticleEffects(int progressPerTick) {
|
||||
if (progressPerTick > 500) {
|
||||
return 1; // 20 times per second
|
||||
} else if (progressPerTick > 360) {
|
||||
return 3;
|
||||
} else if (progressPerTick > 240) {
|
||||
return 7;
|
||||
} else if (progressPerTick > 150) {
|
||||
return 10;
|
||||
} else if (progressPerTick > 90) {
|
||||
return 15;
|
||||
} else if (progressPerTick > 2) {
|
||||
return 20;
|
||||
} else {
|
||||
return 40; // Every 2 seconds
|
||||
}
|
||||
|
||||
if (this.isAccelerated(x, y + 1, z)) {
|
||||
qty += per + qty * mul;
|
||||
}
|
||||
|
||||
if (this.isAccelerated(x, y, z + 1)) {
|
||||
qty += per + qty * mul;
|
||||
}
|
||||
|
||||
if (this.isAccelerated(x - 1, y, z)) {
|
||||
qty += per + qty * mul;
|
||||
}
|
||||
|
||||
if (this.isAccelerated(x, y - 1, z)) {
|
||||
qty += per + qty * mul;
|
||||
}
|
||||
|
||||
if (this.isAccelerated(x, y, z - 1)) {
|
||||
qty += per + qty * mul;
|
||||
}
|
||||
|
||||
return qty;
|
||||
}
|
||||
|
||||
private boolean isAccelerated(final int x, final int y, final int z) {
|
||||
final BlockEntity te = this.world.getBlockEntity(new BlockPos(x, y, z));
|
||||
/**
|
||||
* Gets the extra progress per tick in 1/1000th of a growth tick based on the
|
||||
* surrounding accelerators.
|
||||
*/
|
||||
private int getSpeed(BlockPos pos) {
|
||||
int acceleratorCount = getAcceleratorCount(pos);
|
||||
|
||||
if (acceleratorCount < 0) {
|
||||
return GROWTH_TICK_PROGRESS[0];
|
||||
} else if (acceleratorCount >= GROWTH_TICK_PROGRESS.length) {
|
||||
return GROWTH_TICK_PROGRESS[GROWTH_TICK_PROGRESS.length - 1];
|
||||
} else {
|
||||
return GROWTH_TICK_PROGRESS[acceleratorCount];
|
||||
}
|
||||
}
|
||||
|
||||
private int getAcceleratorCount(BlockPos pos) {
|
||||
int count = 0;
|
||||
|
||||
BlockPos.Mutable testPos = new BlockPos.Mutable();
|
||||
for (Direction direction : Direction.values()) {
|
||||
if (this.isPoweredAccelerator(testPos.set(pos, direction))) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private boolean isPoweredAccelerator(BlockPos pos) {
|
||||
final BlockEntity te = this.world.getBlockEntity(pos);
|
||||
|
||||
return te instanceof ICrystalGrowthAccelerator && ((ICrystalGrowthAccelerator) te).isPowered();
|
||||
}
|
||||
|
||||
// Don't let seeds "float" on water surface
|
||||
@Override
|
||||
public void applyBuoyancy() {
|
||||
ItemStack item = getStack();
|
||||
|
||||
// Make ungrown seeds sink, and fully grown seeds bouyant allowing for
|
||||
// automation based around dropping seeds between 5 CGAs, then catchiung
|
||||
// them on their way up.
|
||||
if (item.getItem() instanceof CrystalSeedItem) {
|
||||
Vec3d v = this.getVelocity();
|
||||
|
||||
// Apply a much smaller acceleration to make them slowly sink
|
||||
double yAccel = this.hasNoGravity() ? 0 : -0.002;
|
||||
|
||||
// Apply the x/z slow-down, and the y acceleration
|
||||
this.setVelocity(v.x * 0.99, v.y + yAccel, v.z * 0.99);
|
||||
|
||||
return;
|
||||
}
|
||||
super.applyBuoyancy();
|
||||
|
||||
@@ -134,8 +134,8 @@ public final class TinyTNTPrimedEntity extends TntEntity implements ICustomEntit
|
||||
return;
|
||||
}
|
||||
|
||||
final Explosion ex = new Explosion(this.world, this, this.getX(), this.getY(), this.getZ(), 0.2f, false,
|
||||
Explosion.DestructionType.BREAK);
|
||||
final Explosion ex = new Explosion(this.world, this, null, null, this.getX(), this.getY(), this.getZ(), 0.2f,
|
||||
false, Explosion.DestructionType.BREAK);
|
||||
|
||||
final Box area = new Box(this.getX() - 1.5, this.getY() - 1.5f, this.getZ() - 1.5, this.getX() + 1.5,
|
||||
this.getY() + 1.5, this.getZ() + 1.5);
|
||||
|
||||
@@ -38,15 +38,18 @@ public class FacadeContainer implements IFacadeContainer {
|
||||
|
||||
private final int facades = 6;
|
||||
private final CableBusStorage storage;
|
||||
private final Runnable changeCallback;
|
||||
|
||||
public FacadeContainer(final CableBusStorage cbs) {
|
||||
public FacadeContainer(final CableBusStorage cbs, Runnable changeCallback) {
|
||||
this.storage = cbs;
|
||||
this.changeCallback = changeCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFacade(final IFacadePart a) {
|
||||
if (this.getFacade(a.getSide()) == null) {
|
||||
this.storage.setFacade(a.getSide().ordinal(), a);
|
||||
this.notifyChange();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -57,6 +60,7 @@ public class FacadeContainer implements IFacadeContainer {
|
||||
if (side != null && side != AEPartLocation.INTERNAL) {
|
||||
if (this.storage.getFacade(side.ordinal()) != null) {
|
||||
this.storage.setFacade(side.ordinal(), null);
|
||||
this.notifyChange();
|
||||
if (host != null) {
|
||||
host.markForUpdate();
|
||||
}
|
||||
@@ -85,6 +89,7 @@ public class FacadeContainer implements IFacadeContainer {
|
||||
for (int x = 0; x < this.facades; x++) {
|
||||
this.storage.setFacade(x, newFacades[x]);
|
||||
}
|
||||
this.notifyChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,4 +181,9 @@ public class FacadeContainer implements IFacadeContainer {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void notifyChange() {
|
||||
this.changeCallback.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import me.shedaniel.math.Rectangle;
|
||||
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.SortDir;
|
||||
import appeng.api.config.SortOrder;
|
||||
@@ -331,4 +333,11 @@ public class FluidTerminalScreen extends AEBaseMEScreen<FluidTerminalContainer>
|
||||
return "guis/terminal.png";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Rectangle> getExclusionZones() {
|
||||
List<Rectangle> zones = super.getExclusionZones();
|
||||
zones.add(new Rectangle(x - 18, y, 18, 40));
|
||||
return zones;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ public class FluidSlotWidget extends CustomSlotWidget {
|
||||
// The tooltip area coincides with the area of the slot
|
||||
int x = getTooltipAreaX();
|
||||
int y = getTooltipAreaY();
|
||||
int width = getTooltipAreaX();
|
||||
int height = getTooltipAreaY();
|
||||
int width = getTooltipAreaWidth();
|
||||
int height = getTooltipAreaHeight();
|
||||
fs.getFluidStack().renderGuiRect(x, y, x + width, y + height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public class FluidExportBusPart extends SharedFluidBusPart {
|
||||
// we'll deduct 1/1000th from storage.
|
||||
long remainderMillibuckets = remainder.getAmount_F().asInt(1000, RoundingMode.DOWN);
|
||||
|
||||
toExtract.setStackSize(remainderMillibuckets);
|
||||
toExtract.decStackSize(remainderMillibuckets);
|
||||
inv.extractItems(toExtract, Actionable.MODULATE, this.source);
|
||||
|
||||
return TickRateModulation.FASTER;
|
||||
|
||||
@@ -128,6 +128,10 @@ public class FluidImportBusPart extends SharedFluidBusPart {
|
||||
aeFluidStack.decStackSize(notInserted.getStackSize());
|
||||
}
|
||||
|
||||
if (aeFluidStack.getStackSize() == 0) {
|
||||
return TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
// Now we need to actually drain the fluid, and use the actual amount we just
|
||||
// inserted
|
||||
extractable.extract(filter, aeFluidStack.getAmount()); // FIXME: If there's a mismatch here, log?
|
||||
@@ -137,7 +141,7 @@ public class FluidImportBusPart extends SharedFluidBusPart {
|
||||
|
||||
return TickRateModulation.IDLE;
|
||||
} catch (GridAccessException e) {
|
||||
e.printStackTrace();
|
||||
// skip
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package appeng.hooks;
|
||||
|
||||
import net.minecraft.block.HopperBlock;
|
||||
import net.minecraft.block.entity.Hopper;
|
||||
import net.minecraft.block.entity.HopperBlockEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import alexiil.mc.lib.attributes.SearchOption;
|
||||
import alexiil.mc.lib.attributes.SearchOptions;
|
||||
import alexiil.mc.lib.attributes.item.ItemAttributes;
|
||||
import alexiil.mc.lib.attributes.item.ItemExtractable;
|
||||
import alexiil.mc.lib.attributes.item.ItemInsertable;
|
||||
import alexiil.mc.lib.attributes.item.ItemInvUtil;
|
||||
import alexiil.mc.lib.attributes.item.compat.FixedInventoryVanillaWrapper;
|
||||
|
||||
// SEE: https://github.com/AlexIIL/LibBlockAttributes/pull/27
|
||||
public final class HopperHooks {
|
||||
|
||||
private HopperHooks() {
|
||||
}
|
||||
|
||||
public static ActionResult tryInsert(HopperBlockEntity hopper) {
|
||||
World world = hopper.getWorld();
|
||||
Direction towards = hopper.getCachedState().get(HopperBlock.FACING);
|
||||
BlockPos targetPos = hopper.getPos().offset(towards);
|
||||
|
||||
if (isVanillaInventoryAt(world, targetPos)) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
ItemInsertable insertable = ItemAttributes.INSERTABLE.getFirstOrNull(world, targetPos,
|
||||
SearchOptions.inDirection(towards));
|
||||
if (insertable == null) {
|
||||
return ActionResult.PASS; // Let Vanilla handle non-LBA enabled inventories and Entities
|
||||
}
|
||||
|
||||
// Get an Extractable for the Hopper's internal inventory
|
||||
ItemExtractable extractable = new FixedInventoryVanillaWrapper(hopper).getExtractable();
|
||||
|
||||
// Try to move any one item from hopper->inventory
|
||||
if (ItemInvUtil.move(extractable, insertable, 1) > 0) {
|
||||
return ActionResult.SUCCESS;
|
||||
} else {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hoppers always search UP for adjacent inventories to extract from.
|
||||
*/
|
||||
private static final SearchOption<? super ItemExtractable> EXTRACT_SEARCH = SearchOptions.inDirection(Direction.UP);
|
||||
|
||||
/**
|
||||
* Tries to extract items from an inventory above the given hopper into the
|
||||
* hopper. Note that the given hopper can also be a hopper minecart.
|
||||
*/
|
||||
public static ActionResult tryExtract(Hopper hopper) {
|
||||
World world = hopper.getWorld();
|
||||
BlockPos blockAbove = new BlockPos(hopper.getHopperX(), hopper.getHopperY() + 1, hopper.getHopperZ());
|
||||
|
||||
if (isVanillaInventoryAt(world, blockAbove)) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
// Get an Extractable for the inventory above the hopper
|
||||
ItemExtractable extractable = ItemAttributes.EXTRACTABLE.getFirstOrNull(world, blockAbove, EXTRACT_SEARCH);
|
||||
if (extractable == null) {
|
||||
return ActionResult.PASS; // Let Vanilla handle non-LBA enabled inventories and Entities
|
||||
}
|
||||
|
||||
// Get an Insertable for the Hopper's internal inventory
|
||||
ItemInsertable insertable = new FixedInventoryVanillaWrapper(hopper).getInsertable();
|
||||
|
||||
// Try to move any one item from inventory->hopper
|
||||
if (ItemInvUtil.move(extractable, insertable, 1) > 0) {
|
||||
return ActionResult.SUCCESS;
|
||||
} else {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isVanillaInventoryAt(World world, BlockPos pos) {
|
||||
// If there's a TE at the target position that implements Inventory (such that
|
||||
// Hopper would handle it itself)
|
||||
// defer to Vanilla to avoid injecting ourselves inbetween Vanilla blocks
|
||||
// needlessly.
|
||||
// ItemAttributes.INSERTABLE would return an auto-converted Inventory in such
|
||||
// cases.
|
||||
return world.getBlockEntity(pos) instanceof Inventory;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2020 Team Appliedenergistics, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.integration.modules.jei;
|
||||
|
||||
import me.shedaniel.rei.api.AutoTransferHandler;
|
||||
import me.shedaniel.rei.api.RecipeDisplay;
|
||||
import me.shedaniel.rei.api.TransferRecipeDisplay;
|
||||
|
||||
import appeng.container.implementations.CraftingTermContainer;
|
||||
|
||||
public class CraftingRecipeTransferHandler extends RecipeTransferHandler<CraftingTermContainer> {
|
||||
|
||||
public CraftingRecipeTransferHandler(Class<CraftingTermContainer> containerClass) {
|
||||
super(containerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AutoTransferHandler.Result doTransferRecipe(CraftingTermContainer container, RecipeDisplay recipe,
|
||||
AutoTransferHandler.Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCrafting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -108,6 +108,8 @@ class FacadeRegistryGenerator implements LiveRecipeGenerator<DefaultShapedDispla
|
||||
ingredients.set(7, Ingredient.ofStacks(cableAnchor));
|
||||
ingredients.set(4, Ingredient.ofStacks(textureItem));
|
||||
|
||||
result.setCount(4);
|
||||
|
||||
return new DefaultShapedDisplay(new ShapedRecipe(id, "", 3, 3, ingredients, result));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2020 Team Appliedenergistics, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.integration.modules.jei;
|
||||
|
||||
import me.shedaniel.rei.api.AutoTransferHandler;
|
||||
import me.shedaniel.rei.api.RecipeDisplay;
|
||||
import me.shedaniel.rei.api.TransferRecipeDisplay;
|
||||
import me.shedaniel.rei.plugin.DefaultPlugin;
|
||||
|
||||
import appeng.container.implementations.PatternTermContainer;
|
||||
|
||||
public class PatternRecipeTransferHandler extends RecipeTransferHandler<PatternTermContainer> {
|
||||
|
||||
PatternRecipeTransferHandler(Class<PatternTermContainer> containerClass) {
|
||||
super(containerClass);
|
||||
}
|
||||
|
||||
protected AutoTransferHandler.Result doTransferRecipe(PatternTermContainer container, RecipeDisplay recipe,
|
||||
AutoTransferHandler.Context context) {
|
||||
|
||||
if (container.isCraftingMode() && recipe.getRecipeCategory() != DefaultPlugin.CRAFTING) {
|
||||
return AutoTransferHandler.Result.createFailed("jei.appliedenergistics2.requires_processing_mode");
|
||||
}
|
||||
|
||||
if (recipe.getResultingEntries().isEmpty()) {
|
||||
return AutoTransferHandler.Result.createFailed("jei.appliedenergistics2.no_output");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCrafting() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,27 +18,27 @@
|
||||
|
||||
package appeng.integration.modules.jei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.ShapedRecipe;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
import me.shedaniel.rei.api.AutoTransferHandler;
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.RecipeDisplay;
|
||||
import me.shedaniel.rei.api.TransferRecipeDisplay;
|
||||
|
||||
import appeng.container.slot.CraftingMatrixSlot;
|
||||
import appeng.container.slot.FakeCraftingMatrixSlot;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.JEIRecipePacket;
|
||||
import appeng.mixins.SlotMixin;
|
||||
import appeng.util.Platform;
|
||||
import appeng.helpers.IContainerCraftingPacket;
|
||||
|
||||
class RecipeTransferHandler<T extends ScreenHandler> implements AutoTransferHandler {
|
||||
abstract class RecipeTransferHandler<T extends ScreenHandler & IContainerCraftingPacket>
|
||||
implements AutoTransferHandler {
|
||||
|
||||
private final Class<T> containerClass;
|
||||
|
||||
@@ -47,67 +47,85 @@ class RecipeTransferHandler<T extends ScreenHandler> implements AutoTransferHand
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result handle(Context context) {
|
||||
if (!(context.getRecipe() instanceof TransferRecipeDisplay)) {
|
||||
return Result.createNotApplicable();
|
||||
public AutoTransferHandler.Result handle(AutoTransferHandler.Context context) {
|
||||
RecipeDisplay recipe = context.getRecipe();
|
||||
|
||||
if (!containerClass.isInstance(context.getContainerScreen().getScreenHandler())) {
|
||||
return AutoTransferHandler.Result.createNotApplicable();
|
||||
}
|
||||
|
||||
ScreenHandler container = context.getContainerScreen().getScreenHandler();
|
||||
T container = containerClass.cast(context.getContainerScreen().getScreenHandler());
|
||||
|
||||
if (!containerClass.isInstance(container)) {
|
||||
return Result.createNotApplicable();
|
||||
final Identifier recipeId = recipe.getRecipeLocation().orElse(null);
|
||||
|
||||
// Check that the recipe can actually be looked up via the manager, i.e. our
|
||||
// facade recipes
|
||||
// have an ID, but are never registered with the recipe manager.
|
||||
boolean canSendReference = true;
|
||||
if (recipeId == null || !context.getMinecraft().world.getRecipeManager().get(recipeId).isPresent()) {
|
||||
canSendReference = false;
|
||||
}
|
||||
|
||||
if (!context.isActuallyCrafting()) {
|
||||
// This is just to check whether the button is enabled
|
||||
return Result.createSuccessful();
|
||||
if (recipe instanceof TransferRecipeDisplay) {
|
||||
TransferRecipeDisplay trd = (TransferRecipeDisplay) recipe;
|
||||
if (trd.getWidth() > 3 || trd.getHeight() > 3) {
|
||||
return AutoTransferHandler.Result.createFailed("jei.appliedenergistics2.recipe_too_large");
|
||||
}
|
||||
} else if (recipe.getInputEntries().size() > 9) {
|
||||
return AutoTransferHandler.Result.createFailed("jei.appliedenergistics2.recipe_too_large");
|
||||
}
|
||||
|
||||
TransferRecipeDisplay transferRecipe = (TransferRecipeDisplay) context.getRecipe();
|
||||
final AutoTransferHandler.Result error = doTransferRecipe(container, recipe, context);
|
||||
|
||||
final CompoundTag recipe = new CompoundTag();
|
||||
if (error != null) {
|
||||
return error;
|
||||
}
|
||||
|
||||
List<List<EntryStack>> ingredients = transferRecipe.getInputEntries();
|
||||
for (int i = 0; i < ingredients.size(); i++) {
|
||||
List<EntryStack> ingredientEntry = ingredients.get(i);
|
||||
|
||||
// Vanilla will pack ingredients if the recipe is less than 3x3
|
||||
int x = i % transferRecipe.getWidth();
|
||||
int y = (i - x) / transferRecipe.getWidth();
|
||||
int slotIndex = 3 * y + x;
|
||||
|
||||
for (final Slot slot : container.slots) {
|
||||
if (slot instanceof CraftingMatrixSlot || slot instanceof FakeCraftingMatrixSlot) {
|
||||
int containerSlotInvIdx = ((SlotMixin) slot).getIndex();
|
||||
if (containerSlotInvIdx == slotIndex) {
|
||||
final ListTag tags = new ListTag();
|
||||
final List<ItemStack> list = new ArrayList<>();
|
||||
|
||||
// prefer pure crystals.
|
||||
for (EntryStack stack : ingredientEntry) {
|
||||
if (Platform.isRecipePrioritized(stack.getItemStack())) {
|
||||
list.add(0, stack.getItemStack());
|
||||
} else {
|
||||
list.add(stack.getItemStack());
|
||||
}
|
||||
}
|
||||
|
||||
for (final ItemStack is : list) {
|
||||
final CompoundTag tag = new CompoundTag();
|
||||
is.toTag(tag);
|
||||
tags.add(tag);
|
||||
}
|
||||
|
||||
recipe.put("#" + containerSlotInvIdx, tags);
|
||||
break;
|
||||
if (context.isActuallyCrafting()) {
|
||||
if (canSendReference) {
|
||||
NetworkHandler.instance().sendToServer(new JEIRecipePacket(recipeId, isCrafting()));
|
||||
} else {
|
||||
// To avoid earlier problems of too large packets being sent that crashed the
|
||||
// client,
|
||||
// as a fallback when the recipe ID could not be resolved, we'll just send the
|
||||
// displayed
|
||||
// items.
|
||||
DefaultedList<Ingredient> flatIngredients = DefaultedList.ofSize(9, Ingredient.EMPTY);
|
||||
ItemStack output = null;
|
||||
for (EntryStack entryStack : recipe.getResultingEntries().get(0)) {
|
||||
if (entryStack.getType() == EntryStack.Type.ITEM) {
|
||||
output = entryStack.getItemStack();
|
||||
}
|
||||
}
|
||||
if (output == null || output.isEmpty()) {
|
||||
return AutoTransferHandler.Result.createFailed("jei.appliedenergistics2.no_output");
|
||||
}
|
||||
|
||||
// Now map the actual ingredients into the output/input
|
||||
for (int i = 0; i < recipe.getInputEntries().size(); i++) {
|
||||
List<EntryStack> inputEntry = recipe.getInputEntries().get(i);
|
||||
if (inputEntry.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
EntryStack first = inputEntry.get(0);
|
||||
if (i < flatIngredients.size()) {
|
||||
ItemStack displayedIngredient = first.getItemStack();
|
||||
if (displayedIngredient != null) {
|
||||
flatIngredients.set(i, Ingredient.method_26964(Stream.of(displayedIngredient)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapedRecipe fallbackRecipe = new ShapedRecipe(recipeId, "", 3, 3, flatIngredients, output);
|
||||
NetworkHandler.instance().sendToServer(new JEIRecipePacket(fallbackRecipe, isCrafting()));
|
||||
}
|
||||
}
|
||||
|
||||
NetworkHandler.instance().sendToServer(new JEIRecipePacket(recipe));
|
||||
|
||||
return Result.createFailed(""); // this will return to the screen
|
||||
return Result.createSuccessful().blocksFurtherHandling();
|
||||
}
|
||||
|
||||
protected abstract AutoTransferHandler.Result doTransferRecipe(T container, RecipeDisplay recipe,
|
||||
AutoTransferHandler.Context context);
|
||||
|
||||
protected abstract boolean isCrafting();
|
||||
}
|
||||
|
||||
@@ -18,13 +18,23 @@
|
||||
|
||||
package appeng.integration.modules.jei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import me.shedaniel.rei.api.BaseBoundsHandler;
|
||||
import me.shedaniel.rei.api.DisplayHelper;
|
||||
import me.shedaniel.rei.api.EntryRegistry;
|
||||
import me.shedaniel.rei.api.EntryStack;
|
||||
import me.shedaniel.rei.api.RecipeHelper;
|
||||
import me.shedaniel.rei.api.plugins.REIPluginV0;
|
||||
@@ -34,12 +44,17 @@ import appeng.api.config.CondenserOutput;
|
||||
import appeng.api.definitions.IDefinitions;
|
||||
import appeng.api.definitions.IItemDefinition;
|
||||
import appeng.api.definitions.IMaterials;
|
||||
import appeng.api.definitions.IParts;
|
||||
import appeng.api.features.AEFeature;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
import appeng.container.implementations.CraftingTermContainer;
|
||||
import appeng.container.implementations.PatternTermContainer;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.core.Api;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.api.definitions.ApiBlocks;
|
||||
import appeng.core.api.definitions.ApiItems;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.integration.abstraction.ReiFacade;
|
||||
import appeng.items.parts.FacadeItem;
|
||||
@@ -47,21 +62,47 @@ import appeng.recipes.handlers.GrinderRecipe;
|
||||
import appeng.recipes.handlers.InscriberRecipe;
|
||||
|
||||
public class ReiPlugin implements REIPluginV0 {
|
||||
|
||||
private static final Identifier ID = new Identifier(AppEng.MOD_ID, "core");
|
||||
|
||||
private final ApiBlocks blocks = Api.INSTANCE.definitions().blocks();
|
||||
|
||||
private final ApiItems items = Api.INSTANCE.definitions().items();
|
||||
|
||||
// Will be hidden if developer items are disabled in the config
|
||||
private final List<Predicate<ItemStack>> developerItems = ImmutableList.of(blocks.cubeGenerator()::isSameAs,
|
||||
blocks.chunkLoader()::isSameAs,
|
||||
// FIXME FABRIC blocks.energyGenerator()::isSameAs,
|
||||
blocks.itemGen()::isSameAs, blocks.phantomNode()::isSameAs,
|
||||
|
||||
items.toolDebugCard()::isSameAs, items.toolEraser()::isSameAs, items.toolMeteoritePlacer()::isSameAs,
|
||||
items.toolReplicatorCard()::isSameAs);
|
||||
|
||||
// Will be hidden if colored cables are hidden
|
||||
private final List<Predicate<ItemStack>> coloredCables;
|
||||
|
||||
public ReiPlugin() {
|
||||
List<Predicate<ItemStack>> predicates = new ArrayList<>();
|
||||
|
||||
IParts parts = Api.instance().definitions().parts();
|
||||
for (AEColor color : AEColor.values()) {
|
||||
if (color == AEColor.TRANSPARENT) {
|
||||
continue; // Keep the Fluix variant
|
||||
}
|
||||
predicates.add(stack -> parts.cableCovered().sameAs(color, stack));
|
||||
predicates.add(stack -> parts.cableDenseCovered().sameAs(color, stack));
|
||||
predicates.add(stack -> parts.cableGlass().sameAs(color, stack));
|
||||
predicates.add(stack -> parts.cableSmart().sameAs(color, stack));
|
||||
predicates.add(stack -> parts.cableDenseSmart().sameAs(color, stack));
|
||||
}
|
||||
coloredCables = ImmutableList.copyOf(predicates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getPluginIdentifier() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
// FIXME FABRIC @Override
|
||||
// FIXME FABRIC public void registerItemSubtypes(ISubtypeRegistration
|
||||
// subtypeRegistry) {
|
||||
// FIXME FABRIC final Optional<Item> maybeFacade =
|
||||
// AEApi.instance().definitions().items().facade().maybeItem();
|
||||
// FIXME FABRIC maybeFacade.ifPresent(subtypeRegistry::useNbtForSubtypes);
|
||||
// FIXME FABRIC }
|
||||
|
||||
@Override
|
||||
public void registerPluginCategories(RecipeHelper recipeHelper) {
|
||||
recipeHelper.registerCategory(new GrinderRecipeCategory());
|
||||
@@ -82,8 +123,8 @@ public class ReiPlugin implements REIPluginV0 {
|
||||
@Override
|
||||
public void registerOthers(RecipeHelper recipeHelper) {
|
||||
// Allow recipe transfer from JEI to crafting and pattern terminal
|
||||
recipeHelper.registerAutoCraftingHandler(new RecipeTransferHandler<>(CraftingTermContainer.class));
|
||||
recipeHelper.registerAutoCraftingHandler(new RecipeTransferHandler<>(PatternTermContainer.class));
|
||||
recipeHelper.registerAutoCraftingHandler(new CraftingRecipeTransferHandler(CraftingTermContainer.class));
|
||||
recipeHelper.registerAutoCraftingHandler(new PatternRecipeTransferHandler(PatternTermContainer.class));
|
||||
|
||||
recipeHelper.removeAutoCraftButton(GrinderRecipeCategory.UID);
|
||||
recipeHelper.removeAutoCraftButton(InscriberRecipeCategory.UID);
|
||||
@@ -91,9 +132,16 @@ public class ReiPlugin implements REIPluginV0 {
|
||||
|
||||
registerWorkingStations(recipeHelper);
|
||||
|
||||
IDefinitions definitions = Api.instance().definitions();
|
||||
recipeHelper.registerLiveRecipeGenerator(new FacadeRegistryGenerator(
|
||||
(FacadeItem) definitions.items().facade().item(), definitions.parts().cableAnchor().stack(1)));
|
||||
if (AEConfig.instance().isFeatureEnabled(AEFeature.ENABLE_FACADE_CRAFTING)) {
|
||||
IDefinitions definitions = Api.instance().definitions();
|
||||
recipeHelper.registerLiveRecipeGenerator(new FacadeRegistryGenerator(
|
||||
(FacadeItem) definitions.items().facade().item(), definitions.parts().cableAnchor().stack(1)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerEntries(EntryRegistry entryRegistry) {
|
||||
entryRegistry.removeEntryIf(this::shouldEntryBeHidden);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,6 +152,17 @@ public class ReiPlugin implements REIPluginV0 {
|
||||
ReiFacade.setInstance(new ReiRuntimeAdapter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBounds(DisplayHelper displayHelper) {
|
||||
BaseBoundsHandler baseBoundsHandler = BaseBoundsHandler.getInstance();
|
||||
|
||||
baseBoundsHandler.registerExclusionZones(AEBaseScreen.class, () -> {
|
||||
AEBaseScreen<?> screen = (AEBaseScreen<?>) MinecraftClient.getInstance().currentScreen;
|
||||
return screen != null ? screen.getExclusionZones() : Collections.emptyList();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void registerWorkingStations(RecipeHelper registration) {
|
||||
IDefinitions definitions = Api.instance().definitions();
|
||||
|
||||
@@ -160,47 +219,36 @@ public class ReiPlugin implements REIPluginV0 {
|
||||
RecipeHelper.getInstance().registerDisplay(info);
|
||||
}
|
||||
|
||||
// FIXME FABRIC @Override
|
||||
// FIXME FABRIC public void registerAdvanced(IAdvancedRegistration registration) {
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC IDefinitions definitions = AEApi.instance().definitions();
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC if (AEConfig.instance().isFeatureEnabled(AEFeature.ENABLE_FACADE_CRAFTING)) {
|
||||
// FIXME FABRIC FacadeItem itemFacade = (FacadeItem) definitions.items().facade().item();
|
||||
// FIXME FABRIC ItemStack cableAnchor = definitions.parts().cableAnchor().stack(1);
|
||||
// FIXME FABRIC registration.addRecipeManagerPlugin(new FacadeRegistryPlugin(itemFacade, cableAnchor));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC @Override
|
||||
// FIXME FABRIC public void onRuntimeAvailable(IJeiRuntime jeiRuntime) {
|
||||
// FIXME FABRIC JEIFacade.setInstance(new JeiRuntimeAdapter(jeiRuntime));
|
||||
// FIXME FABRIC this.hideDebugTools(jeiRuntime);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC private void hideDebugTools(IJeiRuntime jeiRuntime) {
|
||||
// FIXME FABRIC Collection<ItemStack> toRemove = new ArrayList<>();
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC // We use the internal API here as exception as debug tools are not part of the
|
||||
// FIXME FABRIC // public one by design.
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC if (!AEConfig.instance().isFeatureEnabled(AEFeature.UNSUPPORTED_DEVELOPER_TOOLS)) {
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().blocks().cubeGenerator().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().blocks().chunkLoader().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().blocks().energyGenerator().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().blocks().itemGen().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().blocks().phantomNode().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().items().toolDebugCard().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().items().toolEraser().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().items().toolMeteoritePlacer().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC toRemove.add(Api.INSTANCE.definitions().items().toolReplicatorCard().maybeStack(1).orElse(null));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC jeiRuntime.getIngredientManager().removeIngredientsAtRuntime(mezz.jei.api.constants.VanillaTypes.ITEM,
|
||||
// FIXME FABRIC toRemove);
|
||||
// FIXME FABRIC }
|
||||
private boolean shouldEntryBeHidden(EntryStack entryStack) {
|
||||
if (entryStack.getType() != EntryStack.Type.ITEM) {
|
||||
return false;
|
||||
}
|
||||
ItemStack stack = entryStack.getItemStack();
|
||||
|
||||
if (items.dummyFluidItem().isSameAs(stack) || items.facade().isSameAs(stack) // REI will add a broken facade
|
||||
// with no NBT
|
||||
|| blocks.multiPart().isSameAs(stack) || blocks.matrixFrame().isSameAs(stack)
|
||||
|| blocks.paint().isSameAs(stack)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!AEConfig.instance().isFeatureEnabled(AEFeature.UNSUPPORTED_DEVELOPER_TOOLS)) {
|
||||
for (Predicate<ItemStack> developerItem : developerItems) {
|
||||
if (developerItem.test(stack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AEConfig.instance().isDisableColoredCableRecipesInJEI()) {
|
||||
for (Predicate<ItemStack> predicate : coloredCables) {
|
||||
if (predicate.test(stack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
|
||||
package appeng.integration.modules.jei;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import me.shedaniel.rei.api.REIHelper;
|
||||
import me.shedaniel.rei.gui.widget.TextFieldWidget;
|
||||
|
||||
import appeng.integration.abstraction.IRei;
|
||||
|
||||
@@ -29,7 +31,7 @@ class ReiRuntimeAdapter implements IRei {
|
||||
private final REIHelper runtime;
|
||||
|
||||
ReiRuntimeAdapter() {
|
||||
this.runtime = REIHelper.getInstance();
|
||||
this.runtime = Preconditions.checkNotNull(REIHelper.getInstance(), "REI helper was null");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,11 +41,18 @@ class ReiRuntimeAdapter implements IRei {
|
||||
|
||||
@Override
|
||||
public String getSearchText() {
|
||||
return Strings.nullToEmpty(this.runtime.getSearchTextField().getText());
|
||||
TextFieldWidget searchField = this.runtime.getSearchTextField();
|
||||
if (searchField == null) {
|
||||
return "";
|
||||
}
|
||||
return Strings.nullToEmpty(searchField.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSearchText(String searchText) {
|
||||
this.runtime.getSearchTextField().setText(Strings.nullToEmpty(searchText));
|
||||
TextFieldWidget searchField = this.runtime.getSearchTextField();
|
||||
if (searchField != null) {
|
||||
searchField.setText(Strings.nullToEmpty(searchText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package appeng.integration.modules.trenergy;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import team.reborn.energy.Energy;
|
||||
import team.reborn.energy.EnergySide;
|
||||
import team.reborn.energy.EnergyStorage;
|
||||
import team.reborn.energy.EnergyTier;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerUnits;
|
||||
import appeng.api.implementations.items.IAEItemPowerStorage;
|
||||
|
||||
/**
|
||||
* Adapts an itemstack that implements
|
||||
* {@link appeng.api.implementations.items.IAEItemPowerStorage} to the interface
|
||||
* used by TechReborn's energy API.
|
||||
*/
|
||||
public final class ItemPowerStorageAdapter implements EnergyStorage {
|
||||
|
||||
private final IAEItemPowerStorage item;
|
||||
|
||||
private final ItemStack stack;
|
||||
|
||||
public ItemPowerStorageAdapter(IAEItemPowerStorage item, ItemStack stack) {
|
||||
this.item = item;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getStored(EnergySide energySide) {
|
||||
return PowerUnits.AE.convertTo(PowerUnits.TR, this.item.getAECurrentPower(this.stack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStored(double v) {
|
||||
double newPower = PowerUnits.TR.convertTo(PowerUnits.AE, v);
|
||||
double currentPower = this.item.getAECurrentPower(this.stack);
|
||||
double toInject = newPower - currentPower;
|
||||
if (toInject > 0.0000001) {
|
||||
this.item.injectAEPower(stack, toInject, Actionable.MODULATE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxStoredPower() {
|
||||
return PowerUnits.AE.convertTo(PowerUnits.TR, this.item.getAEMaxPower(this.stack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnergyTier getTier() {
|
||||
return EnergyTier.INFINITE;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
// Register our charged items as TechReborn Energy compatible
|
||||
Energy.registerHolder(
|
||||
(Object obj) -> obj instanceof ItemStack && ((ItemStack) obj).getItem() instanceof IAEItemPowerStorage,
|
||||
(Object obj) -> {
|
||||
ItemStack stack = (ItemStack) obj;
|
||||
IAEItemPowerStorage item = (IAEItemPowerStorage) stack.getItem();
|
||||
return new ItemPowerStorageAdapter(item, stack);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,8 @@ package appeng.integration.modules.waila.tile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.item.TooltipContext;
|
||||
@@ -45,6 +47,7 @@ import appeng.tile.misc.ChargerBlockEntity;
|
||||
public final class ChargerWailaDataProvider extends BaseWailaDataProvider {
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void appendBody(List<Text> tooltip, IDataAccessor accessor, IPluginConfig config) {
|
||||
|
||||
final BlockEntity te = accessor.getBlockEntity();
|
||||
|
||||
@@ -26,23 +26,30 @@ import com.google.common.base.Preconditions;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Material;
|
||||
import net.fabricmc.fabric.api.tag.TagRegistry;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.item.TooltipContext;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.tag.FluidTags;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.implementations.items.IGrowableCrystal;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.core.localization.ButtonToolTips;
|
||||
import appeng.entity.GrowingCrystalEntity;
|
||||
import appeng.hooks.AECustomEntityItem;
|
||||
@@ -69,9 +76,15 @@ public class CrystalSeedItem extends AEBaseItem implements IGrowableCrystal, AEC
|
||||
*/
|
||||
private final ItemConvertible grownItem;
|
||||
|
||||
private final Tag<Fluid> improvedFluidTag;
|
||||
|
||||
public CrystalSeedItem(Settings properties, ItemConvertible grownItem) {
|
||||
super(properties);
|
||||
this.grownItem = Preconditions.checkNotNull(grownItem);
|
||||
|
||||
String improvedFluidTagName = AEConfig.instance().getImprovedFluidTag();
|
||||
this.improvedFluidTag = improvedFluidTagName != null ? TagRegistry.fluid(new Identifier(improvedFluidTagName))
|
||||
: null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -97,8 +110,21 @@ public class CrystalSeedItem extends AEBaseItem implements IGrowableCrystal, AEC
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMultiplier(final Block blk, final Material mat) {
|
||||
return 0.5f;
|
||||
public float getMultiplier(BlockState state, @Nullable World world, @Nullable BlockPos pos) {
|
||||
|
||||
// Check for the improved fluid tag and return the improved multiplier
|
||||
FluidState fluidState = state.getFluidState();
|
||||
if (improvedFluidTag != null && fluidState.isIn(improvedFluidTag)) {
|
||||
return AEConfig.instance().getImprovedFluidMultiplier();
|
||||
}
|
||||
|
||||
// Check for the normal supported fluid
|
||||
if (world != null && world.getRegistryKey() == World.NETHER) {
|
||||
// In the nether, use Lava as the "normal" fluid
|
||||
return fluidState.isIn(FluidTags.LAVA) ? 1 : 0;
|
||||
} else {
|
||||
return fluidState.isIn(FluidTags.WATER) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package appeng.items.misc;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import appeng.bootstrap.components.IClientSetupComponent;
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* Exposes a predicate "growth", which is used in the item model to
|
||||
* differentiate the growth stages.
|
||||
*/
|
||||
public class CrystalSeedRendering implements IClientSetupComponent {
|
||||
private final Item item;
|
||||
|
||||
public CrystalSeedRendering(Item item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void setup() {
|
||||
// Expose the growth of the seed to the model system
|
||||
FabricModelPredicateProviderRegistry.register(item, AppEng.makeId("growth"),
|
||||
(is, w, p) -> CrystalSeedItem.getGrowthTicks(is) / (float) CrystalSeedItem.GROWTH_TICKS_REQUIRED);
|
||||
}
|
||||
}
|
||||
@@ -117,39 +117,39 @@ public class EncodedPatternItem extends AEBaseItem implements AEToolItem {
|
||||
return;
|
||||
}
|
||||
|
||||
stack.setCustomName(GuiText.InvalidPattern.text().copy().formatted(Formatting.RED));
|
||||
stack.setCustomName(GuiText.InvalidPattern.text().shallowCopy().formatted(Formatting.RED));
|
||||
|
||||
InvalidPatternHelper invalid = new InvalidPatternHelper(stack);
|
||||
|
||||
final Text label = (invalid.isCraftable() ? GuiText.Crafts.text() : GuiText.Creates.text()).copy()
|
||||
final Text label = (invalid.isCraftable() ? GuiText.Crafts.text() : GuiText.Creates.text()).shallowCopy()
|
||||
.append(": ");
|
||||
final Text and = new LiteralText(" ").append(GuiText.And.text()).append(" ");
|
||||
final Text with = GuiText.With.text().copy().append(": ");
|
||||
final Text and = new LiteralText(" ").shallowCopy().append(GuiText.And.text()).shallowCopy().append(" ");
|
||||
final Text with = GuiText.With.text().shallowCopy().append(": ");
|
||||
|
||||
boolean first = true;
|
||||
for (final InvalidPatternHelper.PatternIngredient output : invalid.getOutputs()) {
|
||||
lines.add((first ? label : and).copy().append(output.getFormattedToolTip()));
|
||||
lines.add((first ? label : and).shallowCopy().append(output.getFormattedToolTip()));
|
||||
first = false;
|
||||
}
|
||||
|
||||
first = true;
|
||||
for (final InvalidPatternHelper.PatternIngredient input : invalid.getInputs()) {
|
||||
lines.add((first ? with : and).copy().append(input.getFormattedToolTip()));
|
||||
lines.add((first ? with : and).shallowCopy().append(input.getFormattedToolTip()));
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (invalid.isCraftable()) {
|
||||
final MutableText substitutionLabel = GuiText.Substitute.text().copy().append(" ");
|
||||
final Text substitutionLabel = GuiText.Substitute.text().shallowCopy().append(" ");
|
||||
final Text canSubstitute = invalid.canSubstitute() ? GuiText.Yes.text() : GuiText.No.text();
|
||||
|
||||
lines.add(substitutionLabel.append(canSubstitute));
|
||||
lines.add(substitutionLabel.shallowCopy().append(canSubstitute));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (stack.hasCustomName()) {
|
||||
stack.removeSubTag("display");
|
||||
stack.removeCustomName();
|
||||
}
|
||||
|
||||
final boolean isCrafting = details.isCraftable();
|
||||
@@ -158,9 +158,9 @@ public class EncodedPatternItem extends AEBaseItem implements AEToolItem {
|
||||
final Collection<IAEItemStack> in = details.getInputs();
|
||||
final Collection<IAEItemStack> out = details.getOutputs();
|
||||
|
||||
final Text label = (isCrafting ? GuiText.Crafts.text() : GuiText.Creates.text()).copy().append(": ");
|
||||
final Text and = new LiteralText(" ").append(GuiText.And.text()).append(" ");
|
||||
final Text with = GuiText.With.text().copy().append(": ");
|
||||
final Text label = (isCrafting ? GuiText.Crafts.text() : GuiText.Creates.text()).shallowCopy().append(": ");
|
||||
final Text and = new LiteralText(" ").shallowCopy().append(GuiText.And.text()).append(" ");
|
||||
final Text with = GuiText.With.text().shallowCopy().append(": ");
|
||||
|
||||
boolean first = true;
|
||||
for (final IAEItemStack anOut : out) {
|
||||
@@ -168,7 +168,7 @@ public class EncodedPatternItem extends AEBaseItem implements AEToolItem {
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add((first ? label : and).copy().append(anOut.getStackSize() + "x ")
|
||||
lines.add((first ? label : and).shallowCopy().append(anOut.getStackSize() + "x ")
|
||||
.append(Platform.getItemDisplayName(anOut)));
|
||||
first = false;
|
||||
}
|
||||
@@ -179,16 +179,16 @@ public class EncodedPatternItem extends AEBaseItem implements AEToolItem {
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add((first ? with : and).copy().append(anIn.getStackSize() + "x ")
|
||||
lines.add((first ? with : and).shallowCopy().append(anIn.getStackSize() + "x ")
|
||||
.append(Platform.getItemDisplayName(anIn)));
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (isCrafting) {
|
||||
final MutableText substitutionLabel = GuiText.Substitute.text().copy().append(" ");
|
||||
final Text substitutionLabel = GuiText.Substitute.text().shallowCopy().append(" ");
|
||||
final Text canSubstitute = substitute ? GuiText.Yes.text() : GuiText.No.text();
|
||||
|
||||
lines.add(substitutionLabel.append(canSubstitute));
|
||||
lines.add(substitutionLabel.shallowCopy().append(canSubstitute));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,14 +299,27 @@ public class EncodedPatternItem extends AEBaseItem implements AEToolItem {
|
||||
final ListTag tagIn = new ListTag();
|
||||
final ListTag tagOut = new ListTag();
|
||||
|
||||
boolean hasInput = false;
|
||||
for (final ItemStack i : in) {
|
||||
tagIn.add(createItemTag(i));
|
||||
if (!i.isEmpty()) {
|
||||
hasInput = true;
|
||||
}
|
||||
}
|
||||
|
||||
Preconditions.checkArgument(hasInput, "cannot encode a pattern that has no inputs.");
|
||||
|
||||
boolean hasNonEmptyOutput = false;
|
||||
for (final ItemStack i : out) {
|
||||
tagOut.add(createItemTag(i));
|
||||
if (!i.isEmpty()) {
|
||||
hasNonEmptyOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Patterns without any outputs are corrupt! Never encode such a pattern.
|
||||
Preconditions.checkArgument(hasNonEmptyOutput, "cannot encode a pattern that has no output.");
|
||||
|
||||
encodedValue.put(EncodedPatternItem.NBT_INGREDIENTS, tagIn);
|
||||
encodedValue.put(EncodedPatternItem.NBT_PRODUCTS, tagOut);
|
||||
return encodedValue;
|
||||
|
||||
@@ -32,6 +32,7 @@ import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.implementations.guiobjects.IGuiItem;
|
||||
@@ -53,6 +54,7 @@ import appeng.core.sync.packets.ClickPacket;
|
||||
import appeng.hooks.AEToolItem;
|
||||
import appeng.items.AEBaseItem;
|
||||
import appeng.items.contents.NetworkToolViewer;
|
||||
import appeng.util.PartHostWrenching;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class NetworkToolItem extends AEBaseItem implements IGuiItem, IAEWrench, AEToolItem {
|
||||
@@ -91,13 +93,17 @@ public class NetworkToolItem extends AEBaseItem implements IGuiItem, IAEWrench,
|
||||
final BlockEntity te = context.getWorld().getBlockEntity(context.getBlockPos());
|
||||
|
||||
if (te instanceof IPartHost) {
|
||||
final SelectedPart part = ((IPartHost) te).selectPart(mop.getPos());
|
||||
Vec3d relativePosition = mop.getPos().subtract(mop.getBlockPos().getX(), mop.getBlockPos().getY(),
|
||||
mop.getBlockPos().getZ());
|
||||
IPartHost host = (IPartHost) te;
|
||||
final SelectedPart part = host.selectPart(relativePosition);
|
||||
|
||||
if (part.part != null || part.facade != null) {
|
||||
if (part.part instanceof INetworkToolAgent && !((INetworkToolAgent) part.part).showNetworkInfo(mop)) {
|
||||
return ActionResult.FAIL;
|
||||
} else if (context.getPlayer().isInSneakingPose()) {
|
||||
return ActionResult.PASS;
|
||||
PartHostWrenching.wrenchPart(context.getWorld(), context.getBlockPos(), host, part);
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
} else if (te instanceof INetworkToolAgent && !((INetworkToolAgent) te).showNetworkInfo(mop)) {
|
||||
@@ -111,13 +117,6 @@ public class NetworkToolItem extends AEBaseItem implements IGuiItem, IAEWrench,
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
// FIXME FABRIC: No direct equivalent
|
||||
// FIXME FABRIC: Might already be handled by onItemUseFirst though
|
||||
// FIXME FABRIC @Override
|
||||
// FIXME FABRIC public boolean doesSneakBypassUse(ItemStack stack, WorldView world, BlockPos pos, PlayerEntity player) {
|
||||
// FIXME FABRIC return true;
|
||||
// FIXME FABRIC }
|
||||
|
||||
public boolean serverSideToolLogic(ItemUsageContext useContext) {
|
||||
BlockPos pos = useContext.getBlockPos();
|
||||
PlayerEntity p = useContext.getPlayer();
|
||||
|
||||
@@ -320,21 +320,21 @@ public class ColorApplicatorItem extends AEBasePoweredItem
|
||||
return w.setBlockState(pos, newState);
|
||||
}
|
||||
|
||||
if (blk instanceof CableBusBlock && p != null) {
|
||||
return ((CableBusBlock) blk).recolorBlock(w, pos, side, newColor.dye, p);
|
||||
}
|
||||
|
||||
BlockEntity be = w.getBlockEntity(pos);
|
||||
if (be instanceof IColorableTile) {
|
||||
IColorableTile ct = (IColorableTile) be;
|
||||
AEColor c = ct.getColor();
|
||||
if (c != newColor) {
|
||||
ct.recolourBlock(side, newColor, null);
|
||||
ct.recolourBlock(side, newColor, p);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blk instanceof CableBusBlock && p != null) {
|
||||
return ((CableBusBlock) blk).recolorBlock(w, pos, side, newColor.dye, p);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,18 +19,27 @@
|
||||
package appeng.items.tools.quartz;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.implementations.items.IAEWrench;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.SelectedPart;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.block.AEBaseBlock;
|
||||
import appeng.hooks.AEToolItem;
|
||||
import appeng.items.AEBaseItem;
|
||||
import appeng.parts.PartPlacement;
|
||||
import appeng.util.PartHostWrenching;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class QuartzWrenchItem extends AEBaseItem implements IAEWrench, AEToolItem {
|
||||
@@ -41,23 +50,55 @@ public class QuartzWrenchItem extends AEBaseItem implements IAEWrench, AEToolIte
|
||||
|
||||
@Override
|
||||
public ActionResult onItemUseFirst(ItemStack stack, ItemUsageContext context) {
|
||||
if (!context.getPlayer().isInSneakingPose() && Platform
|
||||
.hasPermissions(new DimensionalCoord(context.getWorld(), context.getBlockPos()), context.getPlayer())) {
|
||||
PlayerEntity player = context.getPlayer();
|
||||
if (player == null) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
Block block = context.getWorld().getBlockState(context.getBlockPos()).getBlock();
|
||||
if (block instanceof AEBaseBlock) {
|
||||
if (Platform.isClient()) {
|
||||
// TODO 1.10-R - if we return FAIL on client, action will not be sent to server.
|
||||
// Fix that in all Block#onItemUseFirst overrides.
|
||||
return !context.getWorld().isClient ? ActionResult.SUCCESS : ActionResult.PASS;
|
||||
boolean isHoldingShift = player.isInSneakingPose();
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getBlockPos();
|
||||
if (!Platform.hasPermissions(new DimensionalCoord(world, pos), player)) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
Block block = blockState.getBlock();
|
||||
|
||||
if (isHoldingShift) {
|
||||
|
||||
// Wrenching parts of cable buses or other part hosts
|
||||
BlockEntity tile = world.getBlockEntity(pos);
|
||||
IPartHost host = null;
|
||||
if (tile instanceof IPartHost) {
|
||||
host = (IPartHost) tile;
|
||||
}
|
||||
|
||||
if (host != null) {
|
||||
if (!world.isClient) {
|
||||
// Build the relative position within the part
|
||||
Vec3d relPos = context.getHitPos().subtract(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
||||
final SelectedPart sp = PartPlacement.selectPart(player, host, relPos);
|
||||
|
||||
PartHostWrenching.wrenchPart(world, pos, host, sp);
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
// Pass the use onto the block...
|
||||
return block.onUse(blockState, world, pos, player, context.getHand(),
|
||||
new BlockHitResult(context.getHitPos(), context.getSide(), pos, context.hitsInsideBlock()));
|
||||
}
|
||||
|
||||
if (block instanceof AEBaseBlock) {
|
||||
if (!world.isClient) {
|
||||
AEBaseBlock aeBlock = (AEBaseBlock) block;
|
||||
if (aeBlock.rotateAroundFaceAxis(context.getWorld(), context.getBlockPos(), context.getSide())) {
|
||||
context.getPlayer().swingHand(context.getHand());
|
||||
return !context.getWorld().isClient ? ActionResult.SUCCESS : ActionResult.FAIL;
|
||||
if (aeBlock.rotateAroundFaceAxis(world, pos, context.getSide())) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,6 @@ public class Grid implements IGrid {
|
||||
}
|
||||
|
||||
gridNode.getGridProxy().gridChanged();
|
||||
// postEventTo( gridNode, networkChanged );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -502,7 +502,7 @@ public class EnergyGridCache implements IEnergyGrid {
|
||||
private void removeRequester(IAEPowerStorage requester) {
|
||||
Preconditions.checkState(!ongoingInjectOperation,
|
||||
"Cannot modify energy requesters while energy is being injected.");
|
||||
this.requesters.add(requester);
|
||||
this.requesters.remove(requester);
|
||||
}
|
||||
|
||||
private void addProvider(IAEPowerStorage provider) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.Iterator;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.events.LocatableEventAnnounce;
|
||||
@@ -157,12 +156,16 @@ public class QuantumCluster implements ILocatable, IAECluster {
|
||||
if (qc != null) {
|
||||
final World theWorld = qc.center.getWorld();
|
||||
if (!qc.isDestroyed) {
|
||||
ChunkPos cPos = new ChunkPos(qc.center.getPos());
|
||||
if (theWorld.getChunkManager().isChunkLoaded(cPos.x, cPos.z)) {
|
||||
// In future versions, we might actually want to delay the entire registration
|
||||
// until the center
|
||||
// tile begins ticking normally.
|
||||
if (theWorld.isChunkLoaded(qc.center.getPos())) {
|
||||
final World cur = theWorld.getServer().getWorld(theWorld.getRegistryKey());
|
||||
|
||||
final BlockEntity te = theWorld.getBlockEntity(qc.center.getPos());
|
||||
return te != qc.center || theWorld != cur;
|
||||
} else {
|
||||
AELog.warn("Found a registered QNB with serial %s whose chunk seems to be unloaded: %s", qe, qc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,4 +278,17 @@ public class QuantumCluster implements ILocatable, IAECluster {
|
||||
private void setRing(final QuantumBridgeBlockEntity[] ring) {
|
||||
this.Ring = ring;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (center == null) {
|
||||
return "QuantumCluster{no-center}";
|
||||
}
|
||||
|
||||
World world = center.getWorld();
|
||||
BlockPos pos = center.getPos();
|
||||
|
||||
return "QuantumCluster{" + world + "," + pos + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package appeng.mixins;
|
||||
|
||||
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.block.entity.Hopper;
|
||||
import net.minecraft.block.entity.HopperBlockEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
|
||||
import appeng.hooks.HopperHooks;
|
||||
|
||||
// SEE: https://github.com/AlexIIL/LibBlockAttributes/pull/27
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Mixin(HopperBlockEntity.class)
|
||||
public class HopperMixin {
|
||||
|
||||
@Inject(method = "insert", at = @At("HEAD"), cancellable = true, require = 1, allow = 1)
|
||||
private void onInsert(CallbackInfoReturnable<Boolean> cri) {
|
||||
HopperBlockEntity self = (HopperBlockEntity) (Object) this;
|
||||
ActionResult result = HopperHooks.tryInsert(self);
|
||||
if (result != ActionResult.PASS) {
|
||||
cri.setReturnValue(result.isAccepted());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "extract", at = @At("HEAD"), cancellable = true, require = 1, allow = 1)
|
||||
private static void onExtract(Hopper hopper, CallbackInfoReturnable<Boolean> cri) {
|
||||
ActionResult result = HopperHooks.tryExtract(hopper);
|
||||
if (result != ActionResult.PASS) {
|
||||
cri.setReturnValue(result.isAccepted());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user