Resolve most of simple enough compilation errors
This commit is contained in:
parent
9b7e424fc5
commit
64780fbda5
@ -109,7 +109,9 @@ tasks.withType(JavaCompile::class.java) {
|
||||
sourceSets {
|
||||
create("data") {
|
||||
compileClasspath += sourceSets["main"].output
|
||||
compileClasspath += sourceSets["main"].compileClasspath
|
||||
runtimeClasspath += sourceSets["main"].output
|
||||
runtimeClasspath += sourceSets["main"].runtimeClasspath
|
||||
}
|
||||
|
||||
this["main"].resources {
|
||||
@ -189,12 +191,10 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
getByName("dataImplementation").extendsFrom(getByName("implementation"))
|
||||
}
|
||||
|
||||
minecraft {
|
||||
//accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg"))
|
||||
accessTransformers {
|
||||
files("src/main/resources/META-INF/accesstransformer.cfg")
|
||||
}
|
||||
|
||||
runs {
|
||||
configureEach {
|
||||
@ -243,7 +243,7 @@ minecraft {
|
||||
|
||||
mixin {
|
||||
config("$mod_id.mixins.json")
|
||||
config("$mod_id.ad_astra.mixins.json")
|
||||
// config("$mod_id.ad_astra.mixins.json")
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -14,7 +14,7 @@ mc_version=1.21
|
||||
jei_mc_version=1.21
|
||||
curios_mc_version=1.20.2
|
||||
|
||||
forge_gradle_version=[7.0.145,)
|
||||
forge_gradle_version=7.0.153
|
||||
forge_version=21.0.54-beta
|
||||
mixingradle_version=0.7.33
|
||||
mixin_version=0.8.5
|
||||
|
@ -24,14 +24,6 @@ buildscript {
|
||||
}
|
||||
}
|
||||
|
||||
maven(url = "https://repo.spongepowered.org/repository/maven-public/") {
|
||||
name = "Spongepowered"
|
||||
|
||||
content {
|
||||
includeGroup("org.spongepowered")
|
||||
}
|
||||
}
|
||||
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@ -43,7 +35,6 @@ buildscript {
|
||||
classpath(group = "net.neoforged.gradle", name = "userdev", version = forge_gradle_version)
|
||||
classpath(group = "net.neoforged.gradle", name = "mixin", version = forge_gradle_version)
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}")
|
||||
classpath("org.spongepowered:mixingradle:${mixingradle_version}")
|
||||
|
||||
classpath(group = "org.gradle.toolchains", name = "foojay-resolver", version = "0.5.0")
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.data.event.GatherDataEvent
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.neoforged.fml.common.EventBusSubscriber
|
||||
import net.neoforged.fml.common.Mod
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchDataProvider
|
||||
import ru.dbotthepony.mc.otm.block.*
|
||||
@ -55,7 +57,7 @@ import kotlin.properties.Delegates
|
||||
|
||||
internal fun modLocation(string: String) = ResourceLocation(DataGen.MOD_ID, string)
|
||||
|
||||
@Mod.EventBusSubscriber(modid = DataGen.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
@EventBusSubscriber(modid = DataGen.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
|
||||
object DataGen {
|
||||
const val MOD_ID = OverdriveThatMatters.MOD_ID
|
||||
|
||||
|
@ -30,6 +30,8 @@ fun addTags(tagsProvider: TagsProvider) {
|
||||
tagsProvider.plates.add("gold", MItems.GOLD_PLATE)
|
||||
tagsProvider.plates.add("carbon", MItems.CARBON_MESH)
|
||||
|
||||
tagsProvider.items.Appender(ItemTags.MEAT).add(MItems.NUTRIENT_PASTE)
|
||||
|
||||
tagsProvider.fluids.forge("experience").add(MFluids.LIQUID_XP).add(MFluids.LIQUID_XP_FLOWING)
|
||||
tagsProvider.fluidTypes.forge("experience").add(MFluids.LIQUID_XP_TYPE)
|
||||
|
||||
|
@ -18,7 +18,7 @@ import net.minecraftforge.common.Tags
|
||||
import net.minecraftforge.data.event.GatherDataEvent
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.IForgeRegistry
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.datagen.DataGen
|
||||
import java.util.stream.Stream
|
||||
import net.minecraft.data.tags.TagsProvider as MinecraftTagsProvider
|
||||
@ -172,7 +172,7 @@ class TagsProvider(private val event: GatherDataEvent) {
|
||||
val mobEffects = Delegate(ForgeRegistries.MOB_EFFECTS)
|
||||
val damageTypes = Delegate(Registries.DAMAGE_TYPE)
|
||||
|
||||
val androidImmuneEffects = mobEffects.Appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS)
|
||||
val androidImmuneEffects = mobEffects.Appender(MatteryPlayer.ANDROID_IMMUNE_EFFECTS)
|
||||
|
||||
val requiresShovel = blocks.Appender(BlockTags.MINEABLE_WITH_SHOVEL)
|
||||
val requiresAxe = blocks.Appender(BlockTags.MINEABLE_WITH_AXE)
|
||||
|
@ -3,27 +3,26 @@ package ru.dbotthepony.mc.otm;
|
||||
import kotlin.KotlinVersion;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.registries.IdMappingEvent;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.EventPriority;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.neoforged.fml.loading.FMLLoader;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchDescription;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchDescriptions;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchManager;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchResult;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchResults;
|
||||
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature;
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity;
|
||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue;
|
||||
import ru.dbotthepony.mc.otm.block.entity.decorative.DevChestBlockEntity;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer;
|
||||
import ru.dbotthepony.mc.otm.capability.drive.DrivePool;
|
||||
import ru.dbotthepony.mc.otm.client.AndroidAbilityKeyMapping;
|
||||
import ru.dbotthepony.mc.otm.client.AndroidMenuKeyMapping;
|
||||
@ -36,8 +35,8 @@ import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
|
||||
import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer;
|
||||
import ru.dbotthepony.mc.otm.client.render.blockentity.BatteryBankRenderer;
|
||||
import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer;
|
||||
import ru.dbotthepony.mc.otm.compat.adastra.AdAstraCompatKt;
|
||||
import ru.dbotthepony.mc.otm.compat.curios.CuriosCompatKt;
|
||||
import ru.dbotthepony.mc.otm.compat.vanilla.MatteryChestMenu;
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig;
|
||||
import ru.dbotthepony.mc.otm.config.CablesConfig;
|
||||
import ru.dbotthepony.mc.otm.config.ClientConfig;
|
||||
@ -47,22 +46,24 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig;
|
||||
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
|
||||
import ru.dbotthepony.mc.otm.config.ServerConfig;
|
||||
import ru.dbotthepony.mc.otm.config.ToolsConfig;
|
||||
import ru.dbotthepony.mc.otm.data.DecimalProvider;
|
||||
import ru.dbotthepony.mc.otm.item.ChestUpgraderItem;
|
||||
import ru.dbotthepony.mc.otm.item.tool.ExplosiveHammerItem;
|
||||
import ru.dbotthepony.mc.otm.item.armor.TritaniumArmorItem;
|
||||
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem;
|
||||
import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
|
||||
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
|
||||
import ru.dbotthepony.mc.otm.matter.AbstractRegistryAction;
|
||||
import ru.dbotthepony.mc.otm.matter.IMatterFunction;
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager;
|
||||
import ru.dbotthepony.mc.otm.network.*;
|
||||
import ru.dbotthepony.mc.otm.registry.*;
|
||||
import ru.dbotthepony.mc.otm.storage.StorageStack;
|
||||
import ru.dbotthepony.mc.otm.triggers.KillAsAndroidTrigger;
|
||||
import top.theillusivec4.curios.api.CuriosApi;
|
||||
|
||||
import static net.minecraftforge.common.MinecraftForge.EVENT_BUS;
|
||||
import static net.neoforged.neoforge.common.NeoForge.EVENT_BUS;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
// The value here should match an entry in the META-INF/mods.toml file
|
||||
@Mod(OverdriveThatMatters.MOD_ID)
|
||||
@ -72,21 +73,9 @@ public final class OverdriveThatMatters {
|
||||
// Directly reference a log4j logger.
|
||||
public static final String MOD_ID = "overdrive_that_matters";
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final AtomicInteger INGREDIENT_CACHE_INVALIDATION_COUNTER;
|
||||
|
||||
static {
|
||||
try {
|
||||
var f = Ingredient.class.getDeclaredField("INVALIDATION_COUNTER");
|
||||
f.setAccessible(true);
|
||||
INGREDIENT_CACHE_INVALIDATION_COUNTER = (AtomicInteger) f.get(null);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static OverdriveThatMatters INSTANCE;
|
||||
public static ResourceLocation loc(String path) {
|
||||
return new ResourceLocation(MOD_ID, path);
|
||||
return ResourceLocation.fromNamespaceAndPath(MOD_ID, path);
|
||||
}
|
||||
|
||||
private static void checkIfKotlinIsInstalled() {
|
||||
@ -95,9 +84,9 @@ public final class OverdriveThatMatters {
|
||||
}
|
||||
}
|
||||
|
||||
public OverdriveThatMatters() {
|
||||
public OverdriveThatMatters(IEventBus bus, Dist dist, ModContainer container) {
|
||||
if (INSTANCE != null) {
|
||||
throw new IllegalStateException("yo what the fuck");
|
||||
throw new IllegalStateException("wei wei wei... hello?");
|
||||
}
|
||||
|
||||
try {
|
||||
@ -121,35 +110,67 @@ public final class OverdriveThatMatters {
|
||||
|
||||
INSTANCE = this;
|
||||
|
||||
var modBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
bus.addListener(MRegistry.INSTANCE::register);
|
||||
|
||||
MRegistry.INSTANCE.initialize(modBus);
|
||||
MatterManager.INSTANCE.initialize(modBus);
|
||||
MBlocks.INSTANCE.register(bus);
|
||||
MFluids.INSTANCE.register(bus);
|
||||
MBlockEntities.INSTANCE.register(bus);
|
||||
MEntityTypes.INSTANCE.register(bus);
|
||||
MMenus.INSTANCE.register(bus);
|
||||
MItems.INSTANCE.register(bus);
|
||||
AndroidFeatures.INSTANCE.register(bus);
|
||||
MSoundEvents.INSTANCE.register(bus);
|
||||
LootModifiers.INSTANCE.register(bus);
|
||||
MItemFunctionTypes.INSTANCE.register(bus);
|
||||
MLootItemConditions.INSTANCE.register(bus);
|
||||
MRecipes.INSTANCE.register(bus);
|
||||
MDataComponentTypes.INSTANCE.register(bus);
|
||||
MArmorMaterials.INSTANCE.register(bus);
|
||||
|
||||
modBus.addListener(EventPriority.HIGHEST, this::setup);
|
||||
modBus.addListener(EventPriority.NORMAL, this::setupClient);
|
||||
modBus.addListener(EventPriority.NORMAL, MatteryCapability::register);
|
||||
StorageStack.Companion.register(bus);
|
||||
MatteryChestMenu.Companion.register(bus);
|
||||
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
modBus.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::register);
|
||||
modBus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register);
|
||||
modBus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register);
|
||||
modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register);
|
||||
modBus.addListener(EventPriority.NORMAL, MCreativeTabs.INSTANCE::register);
|
||||
MCreativeTabs.INSTANCE.initialize(bus);
|
||||
|
||||
modBus.addListener(EventPriority.NORMAL, BatteryBankRenderer.Companion::onRegisterAdditionalModels);
|
||||
modBus.addListener(EventPriority.NORMAL, MatterBatteryBankRenderer.Companion::onRegisterAdditionalModels);
|
||||
});
|
||||
bus.addListener(NetworkPacketsKt::registerNetworkPackets);
|
||||
|
||||
ClientConfig.INSTANCE.register();
|
||||
ServerConfig.INSTANCE.register();
|
||||
CablesConfig.INSTANCE.register();
|
||||
ServerCompatConfig.INSTANCE.register();
|
||||
AndroidConfig.INSTANCE.register();
|
||||
ExopackConfig.INSTANCE.register();
|
||||
ItemsConfig.INSTANCE.register();
|
||||
MachinesConfig.INSTANCE.register();
|
||||
ToolsConfig.INSTANCE.register();
|
||||
DecimalProvider.Companion.register(bus);
|
||||
AndroidResearchDescription.Companion.register(bus);
|
||||
AndroidResearchDescriptions.INSTANCE.register(bus);
|
||||
AndroidResearchResult.Companion.register(bus);
|
||||
AndroidResearchResults.INSTANCE.register(bus);
|
||||
|
||||
AbstractRegistryAction.Companion.register(bus);
|
||||
IMatterFunction.Companion.register(bus);
|
||||
|
||||
MRegistry.INSTANCE.initialize(bus);
|
||||
MatterManager.INSTANCE.initialize(bus);
|
||||
|
||||
bus.addListener(EventPriority.HIGHEST, this::setup);
|
||||
bus.addListener(EventPriority.NORMAL, this::setupClient);
|
||||
|
||||
if (FMLLoader.getDist() == Dist.CLIENT) {
|
||||
bus.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::register);
|
||||
bus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register);
|
||||
bus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register);
|
||||
bus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register);
|
||||
bus.addListener(EventPriority.NORMAL, MCreativeTabs.INSTANCE::register);
|
||||
|
||||
bus.addListener(EventPriority.NORMAL, BatteryBankRenderer.Companion::onRegisterAdditionalModels);
|
||||
bus.addListener(EventPriority.NORMAL, MatterBatteryBankRenderer.Companion::onRegisterAdditionalModels);
|
||||
|
||||
MBlockColors.INSTANCE.register(bus);
|
||||
}
|
||||
|
||||
ClientConfig.INSTANCE.register(container);
|
||||
ServerConfig.INSTANCE.register(container);
|
||||
CablesConfig.INSTANCE.register(container);
|
||||
ServerCompatConfig.INSTANCE.register(container);
|
||||
AndroidConfig.INSTANCE.register(container);
|
||||
ExopackConfig.INSTANCE.register(container);
|
||||
ItemsConfig.INSTANCE.register(container);
|
||||
MachinesConfig.INSTANCE.register(container);
|
||||
ToolsConfig.INSTANCE.register(container);
|
||||
}
|
||||
|
||||
private void setup(final FMLCommonSetupEvent event) {
|
||||
@ -158,23 +179,22 @@ public final class OverdriveThatMatters {
|
||||
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopped);
|
||||
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopping);
|
||||
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStarting);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onLevelTick);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onServerTick);
|
||||
EVENT_BUS.addListener(EventPriority.HIGH, GlobalEventHandlerKt::onLevelTickPre);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onLevelTickPost);
|
||||
EVENT_BUS.addListener(EventPriority.HIGH, GlobalEventHandlerKt::onServerTickPre);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onServerTickPost);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerTick);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::isMobEffectApplicable);
|
||||
EVENT_BUS.addListener(EventPriority.LOW, MatteryPlayerCapability.Companion::onHurtEvent);
|
||||
EVENT_BUS.addListener(EventPriority.HIGH, MatteryPlayerCapability.Companion::onAttackEvent);
|
||||
EVENT_BUS.addGenericListener(Entity.class, EventPriority.NORMAL, MatteryPlayerCapability.Companion::onAttachCapabilityEvent);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerChangeDimensionEvent);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayerCapability.Companion::onPlayerDeath);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerCloneEvent);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStartTracking);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStopTracking);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::addCommands);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onPlayerTickPre);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onPlayerTickPost);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::isMobEffectApplicable);
|
||||
EVENT_BUS.addListener(EventPriority.LOW, MatteryPlayer.Companion::onHurtEvent);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onPlayerChangeDimensionEvent);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayer.Companion::onPlayerDeath);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onPlayerCloneEvent);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onStartTracking);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::onStopTracking);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayer.Companion::addCommands);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::tick);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::tick);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, PortableCondensationDriveItem.Companion::onPickupEvent);
|
||||
|
||||
@ -191,6 +211,7 @@ public final class OverdriveThatMatters {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onWatch);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onForget);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::playerDisconnected);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::postLevelTick);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, KillAsAndroidTrigger.INSTANCE::onKill);
|
||||
|
||||
@ -203,29 +224,14 @@ public final class OverdriveThatMatters {
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, DevChestBlockEntity.Companion::mappingsChanged);
|
||||
|
||||
MatteryPlayerNetworkChannel.INSTANCE.register();
|
||||
MenuNetworkChannel.INSTANCE.register();
|
||||
WeaponNetworkChannel.INSTANCE.register();
|
||||
GenericNetworkChannel.INSTANCE.register();
|
||||
|
||||
if (ModList.get().isLoaded(CuriosApi.MODID)) {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, CuriosCompatKt::onCuriosSlotModifiersUpdated);
|
||||
}
|
||||
|
||||
if (AdAstraCompatKt.isAdAstraLoaded()) {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AdAstraCompatKt::onDamageEvent);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AdAstraCompatKt::onMatteryTick);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupClient(final FMLClientSetupEvent event) {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::tooltipEvent);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::playerRenderHook);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::fovHook);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::clickHook);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::renderViewModel);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryGUI.INSTANCE::onScreenRender);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryGUI.INSTANCE::onOpenGUIEvent);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryGUI.INSTANCE::onRenderGuiEvent);
|
||||
|
@ -1,9 +1,12 @@
|
||||
package ru.dbotthepony.mc.otm.capability;
|
||||
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityToken;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.neoforged.neoforge.capabilities.BlockCapability;
|
||||
import net.neoforged.neoforge.capabilities.ItemCapability;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.block.entity.cable.EnergyCableBlockEntity;
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage;
|
||||
@ -12,57 +15,56 @@ import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider;
|
||||
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage;
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNode;
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNode;
|
||||
import top.theillusivec4.curios.api.type.capability.ICurio;
|
||||
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class MatteryCapability {
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<IMatteryEnergyStorage> ENERGY = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final BlockCapability<IMatteryEnergyStorage, @Nullable Direction> BLOCK_ENERGY = BlockCapability.createSided(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "energy"), IMatteryEnergyStorage.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<MatteryPlayerCapability> MATTERY_PLAYER = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final ItemCapability<IMatteryEnergyStorage, Void> ITEM_ENERGY = ItemCapability.createVoid(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "energy"), IMatteryEnergyStorage.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<IMatterStorage> MATTER = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final ItemCapability<IMatterStorage, Void> MATTER_ITEM = ItemCapability.createVoid(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "matter"), IMatterStorage.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<MatterNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final BlockCapability<IMatterStorage, @Nullable Direction> MATTER_BLOCK = BlockCapability.createSided(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "matter"), IMatterStorage.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<IPatternStorage> PATTERN = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final BlockCapability<MatterNode, @Nullable Direction> MATTER_NODE = BlockCapability.createSided(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "matter_node"), MatterNode.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<IReplicationTaskProvider> TASK = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final ItemCapability<IPatternStorage, Void> PATTERN_ITEM = ItemCapability.createVoid(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "pattern"), IPatternStorage.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<IMatteryDrive<?>> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final BlockCapability<IPatternStorage, @Nullable Direction> PATTERN_BLOCK = BlockCapability.createSided(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "pattern"), IPatternStorage.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<StorageNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final BlockCapability<IReplicationTaskProvider, Void> REPLICATION_TASK = BlockCapability.createVoid(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "replication_task"), IReplicationTaskProvider.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<EnergyCableBlockEntity.Node> ENERGY_CABLE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final ItemCapability<IMatteryDrive, Void> CONDENSATION_DRIVE = ItemCapability.createVoid(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "condensation_drive"), IMatteryDrive.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<ICuriosItemHandler> CURIOS_INVENTORY = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final BlockCapability<StorageNode, @Nullable Direction> STORAGE_NODE = BlockCapability.createSided(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "storage_node"), StorageNode.class);
|
||||
|
||||
// TODO: remove this
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final BlockCapability<EnergyCableBlockEntity.Node, Void> ENERGY_CABLE_NODE = BlockCapability.createVoid(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "energy_cable_node"), EnergyCableBlockEntity.Node.class);
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<ICurio> CURIOS_ITEM = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<IMatteryUpgrade> UPGRADE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final ItemCapability<IMatteryUpgrade, Void> UPGRADE = ItemCapability.createVoid(ResourceLocation.fromNamespaceAndPath(OverdriveThatMatters.MOD_ID, "machine_upgrade"), IMatteryUpgrade.class);
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.client.model;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.PlayerModel;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
@ -21,11 +19,8 @@ import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
|
@ -18,7 +18,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@ -61,7 +61,7 @@ public class MixinInventory {
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void dropAll(CallbackInfo ci) {
|
||||
MatteryPlayerCapability.inventoryDropAll((Inventory)(Object)this);
|
||||
MatteryPlayer.inventoryDropAll((Inventory)(Object)this);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@ -69,7 +69,7 @@ public class MixinInventory {
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void clearContent(CallbackInfo ci) {
|
||||
MatteryPlayerCapability.inventoryClearContent((Inventory)(Object)this);
|
||||
MatteryPlayer.inventoryClearContent((Inventory)(Object)this);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
|
@ -5,10 +5,8 @@ import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
public class MixinMinecraft {
|
||||
@ -22,7 +20,7 @@ public class MixinMinecraft {
|
||||
private int pickBlock(Inventory inventory, ItemStack itemStack) {
|
||||
int i = inventory.findSlotMatchingItem(itemStack);
|
||||
|
||||
MatteryPlayerCapability.pickBlockHook(i, itemStack);
|
||||
MatteryPlayer.pickBlockHook(i, itemStack);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.mixin;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public class MixinPatchProjectileFinder {
|
||||
@Inject(
|
||||
method = "getProjectile(Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net.minecraftforge.common.ForgeHooks.getProjectile(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;",
|
||||
ordinal = 2,
|
||||
shift = At.Shift.BEFORE,
|
||||
remap = false
|
||||
),
|
||||
cancellable = true)
|
||||
private void exosuitGetProjectileHook(ItemStack weaponItem, CallbackInfoReturnable<ItemStack> hook) {
|
||||
ItemStack result = MatteryPlayerCapability.getProjectileHook((Player) ((Object) this), weaponItem);
|
||||
|
||||
if (result != null) {
|
||||
hook.setReturnValue(result);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +1,85 @@
|
||||
package ru.dbotthepony.mc.otm.mixin;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public class MixinPlayer {
|
||||
public class MixinPlayer implements IMatteryPlayer {
|
||||
private Player otmSelf() {
|
||||
return (Player) (Object) this;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "getProjectile(Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net.minecraftforge.common.ForgeHooks.getProjectile(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;",
|
||||
ordinal = 2,
|
||||
shift = At.Shift.BEFORE,
|
||||
remap = false
|
||||
),
|
||||
cancellable = true)
|
||||
private void exosuitGetProjectileHook(ItemStack weaponItem, CallbackInfoReturnable<ItemStack> hook) {
|
||||
ItemStack result = MatteryPlayer.getProjectileHook(otmSelf(), weaponItem);
|
||||
|
||||
if (result != null) {
|
||||
hook.setReturnValue(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "destroyVanishingCursedItems()V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void destroyVanishingCursedItems(CallbackInfo ci) {
|
||||
MatteryPlayerCapability.playerDestroyVanishingCursedItems((Player)(Object)this);
|
||||
MatteryPlayer.playerDestroyVanishingCursedItems(otmSelf());
|
||||
}
|
||||
|
||||
private MatteryPlayer otmPlayer;
|
||||
|
||||
@Inject(
|
||||
method = "<init>(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;FLcom/mojang/authlib/GameProfile;)V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void constructOtmPlayer(Level p_250508_, BlockPos p_250289_, float p_251702_, GameProfile p_252153_, CallbackInfo ci) {
|
||||
otmPlayer = new MatteryPlayer(otmSelf());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MatteryPlayer getOtmPlayer() {
|
||||
return Objects.requireNonNull(otmPlayer, "Something went horribly wrong, otmPlayer is null");
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "addAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void addAdditionalSaveData(CompoundTag data, CallbackInfo ci) {
|
||||
data.put("overdrive_that_matters_player", otmPlayer.serializeNBT(otmSelf().registryAccess()));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "readAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void readAdditionalSaveData(CompoundTag data, CallbackInfo ci) {
|
||||
otmPlayer.deserializeNBT(data.getCompound("overdrive_that_matters_player"), otmSelf().registryAccess());
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.mixin.compat.ad_astra;
|
||||
|
||||
import earth.terrarium.ad_astra.common.entity.system.EntityOxygenSystem;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
|
||||
|
||||
@Mixin(EntityOxygenSystem.class)
|
||||
public class EntityOxygenSystemMixin {
|
||||
@Inject(
|
||||
method = "oxygenTick(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/server/level/ServerLevel;)V",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true,
|
||||
remap = false
|
||||
)
|
||||
private static void oxygenTick(LivingEntity entity, ServerLevel level, CallbackInfo hook) {
|
||||
if (entity instanceof Player && ServerCompatConfig.AdAstra.INSTANCE.getANDROIDS_DO_NOT_NEED_OXYGEN()) {
|
||||
entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
|
||||
if (it.isAndroid()) {
|
||||
hook.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.mixin.compat.ad_astra;
|
||||
|
||||
import earth.terrarium.ad_astra.common.entity.system.EntityTemperatureSystem;
|
||||
import earth.terrarium.ad_astra.common.util.ModUtils;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
|
||||
|
||||
// STAHP!
|
||||
@Mixin(EntityTemperatureSystem.class)
|
||||
public class EntityTemperatureSystemMixin {
|
||||
@Inject(
|
||||
method = "temperatureTick(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/server/level/ServerLevel;)V",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true,
|
||||
remap = false
|
||||
)
|
||||
private static void temperatureTick(LivingEntity entity, ServerLevel level, CallbackInfo hook) {
|
||||
if (ServerCompatConfig.AdAstra.INSTANCE.getWHATS_UP_WITH_TEMPERATURE() && !ModUtils.planetHasAtmosphere(level)) {
|
||||
hook.cancel();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.mixin.compat.ad_astra;
|
||||
|
||||
import earth.terrarium.ad_astra.common.util.OxygenUtils;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
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 ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
|
||||
|
||||
@Mixin(OxygenUtils.class)
|
||||
public class OxygenUtilsMixin {
|
||||
@Inject(
|
||||
method = "entityHasOxygen(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;)Z",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true,
|
||||
remap = false
|
||||
)
|
||||
private static void entityHasOxygen(Level level, LivingEntity entity, CallbackInfoReturnable<Boolean> hook) {
|
||||
if (entity instanceof Player && ServerCompatConfig.AdAstra.INSTANCE.getANDROIDS_DO_NOT_NEED_OXYGEN()) {
|
||||
entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
|
||||
if (it.isAndroid()) {
|
||||
hook.setReturnValue(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -4,16 +4,19 @@
|
||||
package ru.dbotthepony.mc.otm
|
||||
|
||||
import net.minecraft.client.server.IntegratedServer
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.api.distmarker.Dist
|
||||
import net.minecraftforge.event.TickEvent
|
||||
import net.minecraftforge.event.TickEvent.ServerTickEvent
|
||||
import net.minecraftforge.event.TickEvent.LevelTickEvent
|
||||
import net.minecraftforge.event.server.ServerAboutToStartEvent
|
||||
import net.minecraftforge.event.server.ServerStoppedEvent
|
||||
import net.minecraftforge.event.server.ServerStoppingEvent
|
||||
import net.minecraftforge.fml.loading.FMLLoader
|
||||
import net.neoforged.api.distmarker.Dist
|
||||
import net.neoforged.bus.api.EventPriority
|
||||
import net.neoforged.bus.api.SubscribeEvent
|
||||
import net.neoforged.fml.common.EventBusSubscriber
|
||||
import net.neoforged.fml.loading.FMLLoader
|
||||
import net.neoforged.neoforge.event.server.ServerAboutToStartEvent
|
||||
import net.neoforged.neoforge.event.server.ServerStoppedEvent
|
||||
import net.neoforged.neoforge.event.server.ServerStoppingEvent
|
||||
import net.neoforged.neoforge.event.tick.LevelTickEvent
|
||||
import net.neoforged.neoforge.event.tick.ServerTickEvent
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
|
||||
@ -24,7 +27,6 @@ import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
|
||||
import ru.dbotthepony.mc.otm.core.util.ITickable
|
||||
import ru.dbotthepony.mc.otm.core.util.TickList
|
||||
import ru.dbotthepony.mc.otm.graph.GraphNodeList
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworkChannel
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
@ -43,6 +45,15 @@ val isClient: Boolean by lazy { FMLLoader.getDist() == Dist.CLIENT }
|
||||
val UNIVERSE_TICKS get() = postServerTick.ticks
|
||||
val Level.ticksPassed get() = postWorldTick.computeIfAbsent(this) { TickList() }.ticks
|
||||
|
||||
@Deprecated("Use when absolutely necessary, like context-less methods/properties")
|
||||
val Registries: HolderLookup.Provider get() {
|
||||
if (isClient) {
|
||||
return NULLABLE_MINECRAFT_SERVER?.registryAccess() ?: minecraft.level?.registryAccess() ?: throw IllegalStateException("Not in game")
|
||||
} else {
|
||||
return NULLABLE_MINECRAFT_SERVER?.registryAccess() ?: throw IllegalStateException("Not in game")
|
||||
}
|
||||
}
|
||||
|
||||
fun <V> lazyPerServer(fn: (MinecraftServer) -> V): Lazy<V> {
|
||||
return AtomicallyInvalidatedLazy(serverCounter) {
|
||||
if (!SERVER_IS_LIVE)
|
||||
@ -169,31 +180,30 @@ var SERVER_IS_LIVE = false
|
||||
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
|
||||
fun onServerTick(event: ServerTickEvent) {
|
||||
if (event.phase === TickEvent.Phase.START) {
|
||||
fun onServerTickPre(event: ServerTickEvent.Pre) {
|
||||
preServerTick.tick()
|
||||
serverThreads.add(Thread.currentThread())
|
||||
} else {
|
||||
}
|
||||
|
||||
fun onServerTickPost(event: ServerTickEvent.Post) {
|
||||
postServerTick.tick()
|
||||
// чтоб не плодить кучу подписчиков, вызовем напрямую отсюда
|
||||
GraphNodeList.tick()
|
||||
AbstractProfiledStorage.onServerPostTick()
|
||||
}
|
||||
}
|
||||
|
||||
fun onLevelTick(event: LevelTickEvent) {
|
||||
if (event.phase === TickEvent.Phase.START) {
|
||||
fun onLevelTickPre(event: LevelTickEvent.Pre) {
|
||||
preWorldTick[event.level]?.tick()
|
||||
|
||||
if (event.side.isClient) {
|
||||
if (event.level.isClientSide) {
|
||||
clientThreads.add(Thread.currentThread())
|
||||
} else if (event.side.isServer) {
|
||||
} else {
|
||||
serverThreads.add(Thread.currentThread())
|
||||
}
|
||||
} else {
|
||||
postWorldTick[event.level]?.tick()
|
||||
MatteryBlockEntity.postLevelTick(event)
|
||||
}
|
||||
|
||||
fun onLevelTickPost(event: LevelTickEvent.Post) {
|
||||
postWorldTick[event.level]?.tick()
|
||||
}
|
||||
|
||||
fun onceServerPre(ticker: ITickable) {
|
||||
|
@ -1,13 +1,13 @@
|
||||
package ru.dbotthepony.mc.otm
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import net.minecraftforge.registries.IForgeRegistry
|
||||
import net.neoforged.neoforge.common.ModConfigSpec
|
||||
import ru.dbotthepony.mc.otm.config.getValue
|
||||
import java.util.LinkedList
|
||||
|
||||
abstract class ObservedConfigList<V : Any>(val parent: ForgeConfigSpec.ConfigValue<MutableList<String>>, private val allowNulls: Boolean = false) : AbstractMutableList<V>(), RandomAccess {
|
||||
abstract class ObservedConfigList<V : Any>(val parent: ModConfigSpec.ConfigValue<MutableList<String>>, private val allowNulls: Boolean = false) : AbstractMutableList<V>(), RandomAccess {
|
||||
private val rawValue: MutableList<String> by parent
|
||||
private val observedValue = LinkedList<String>()
|
||||
private val parsedView: ArrayList<V> = ArrayList()
|
||||
@ -140,33 +140,3 @@ abstract class ObservedConfigList<V : Any>(val parent: ForgeConfigSpec.ConfigVal
|
||||
return parsedView[index]
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Any> ForgeConfigSpec.Builder.defineObjectList(
|
||||
name: String,
|
||||
defaultValues: () -> List<T>,
|
||||
write: (value: T) -> Pair<String, T>?,
|
||||
read: (value: String) -> T?
|
||||
): ObservedConfigList<T> {
|
||||
val parent = defineListAllowEmpty(name.split('.'), { defaultValues.invoke().mapNotNull { write.invoke(it)?.first }.toMutableList()}, { it is String }) as ForgeConfigSpec.ConfigValue<MutableList<String>>
|
||||
|
||||
return object : ObservedConfigList<T>(parent) {
|
||||
override fun toString(value: T): Pair<String, T>? {
|
||||
return write.invoke(value)
|
||||
}
|
||||
|
||||
override fun fromString(value: String): T? {
|
||||
return read.invoke(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Obviously better use tags")
|
||||
fun <T : Any> ForgeConfigSpec.Builder.defineForgeObjectList(
|
||||
name: String,
|
||||
defaultValues: () -> List<T>,
|
||||
registry: IForgeRegistry<T>
|
||||
): ObservedConfigList<T> {
|
||||
return defineObjectList(name, defaultValues,
|
||||
write = { (registry.getKey(it)?.toString() ?: return@defineObjectList null) to it },
|
||||
read = { registry.getValue(ResourceLocation(it)) })
|
||||
}
|
||||
|
@ -2,10 +2,10 @@ package ru.dbotthepony.mc.otm.android
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.Camera
|
||||
import net.minecraftforge.client.event.RenderLevelStageEvent
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import net.neoforged.neoforge.client.event.RenderLevelStageEvent
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
|
||||
abstract class AndroidActiveFeature(type: AndroidFeatureType<*>, android: MatteryPlayerCapability) : AndroidSwitchableFeature(type, android) {
|
||||
abstract class AndroidActiveFeature(type: AndroidFeatureType<*>, android: MatteryPlayer) : AndroidSwitchableFeature(type, android) {
|
||||
/**
|
||||
* return true to send packet to server if [isClient] is true
|
||||
*
|
||||
|
@ -1,18 +1,18 @@
|
||||
package ru.dbotthepony.mc.otm.android
|
||||
|
||||
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.minecraftforge.event.entity.living.LivingAttackEvent
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable
|
||||
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
|
||||
import ru.dbotthepony.kommons.io.DelegateSyncher
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import java.io.InputStream
|
||||
|
||||
abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayerCapability) : INBTSerializable<CompoundTag> {
|
||||
abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayer) : INBTSerializable<CompoundTag> {
|
||||
val ply get() = android.ply
|
||||
val syncher = DelegateSyncher()
|
||||
val syncherRemote = syncher.Remote()
|
||||
@ -37,8 +37,7 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt
|
||||
open fun applyModifiers() {}
|
||||
open fun removeModifiers() {}
|
||||
|
||||
open fun onHurt(event: LivingHurtEvent) {}
|
||||
open fun onAttack(event: LivingAttackEvent) {}
|
||||
open fun onHurt(event: LivingIncomingDamageEvent) {}
|
||||
|
||||
open fun collectNetworkPayload(): FastByteArrayOutputStream? {
|
||||
syncher.observe()
|
||||
@ -49,23 +48,23 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt
|
||||
syncher.read(stream)
|
||||
}
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["level"] = level
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag) {
|
||||
level = nbt.getInt("level")
|
||||
}
|
||||
}
|
||||
|
||||
class DummyAndroidFeature(type: AndroidFeatureType<*>, android: MatteryPlayerCapability) : AndroidFeature(type, android) {
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
class DummyAndroidFeature(type: AndroidFeatureType<*>, android: MatteryPlayer) : AndroidFeature(type, android) {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return CompoundTag()
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,26 +4,26 @@ import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.ComponentContents
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.contents.TranslatableContents
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.core.getKeyNullable
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
|
||||
open class AndroidFeatureType<T : AndroidFeature> {
|
||||
protected val factory: (AndroidFeatureType<T>, MatteryPlayerCapability) -> T
|
||||
protected val factory: (AndroidFeatureType<T>, MatteryPlayer) -> T
|
||||
|
||||
constructor(factory: (MatteryPlayerCapability) -> T) : super() {
|
||||
constructor(factory: (MatteryPlayer) -> T) : super() {
|
||||
this.factory = { _, capability -> factory.invoke(capability) }
|
||||
}
|
||||
|
||||
constructor(factory: (AndroidFeatureType<T>, MatteryPlayerCapability) -> T) : super() {
|
||||
constructor(factory: (AndroidFeatureType<T>, MatteryPlayer) -> T) : super() {
|
||||
this.factory = factory
|
||||
}
|
||||
|
||||
fun create(android: MatteryPlayerCapability): T {
|
||||
fun create(android: MatteryPlayer): T {
|
||||
return factory.invoke(this, android)
|
||||
}
|
||||
|
||||
open fun isApplicable(android: MatteryPlayerCapability) = true
|
||||
open fun isApplicable(android: MatteryPlayer) = true
|
||||
|
||||
val registryName by lazy {
|
||||
MRegistry.ANDROID_FEATURES.getKeyNullable(this)
|
||||
|
@ -2,19 +2,19 @@ package ru.dbotthepony.mc.otm.android
|
||||
|
||||
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.minecraftforge.eventbus.api.Event
|
||||
import net.minecraftforge.eventbus.api.Event.HasResult
|
||||
import net.neoforged.bus.api.Event
|
||||
import net.neoforged.neoforge.common.NeoForge
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable
|
||||
import ru.dbotthepony.kommons.io.DelegateSyncher
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.awareItemsStream
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
@ -25,33 +25,27 @@ import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
|
||||
import java.io.InputStream
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlayerCapability) : INBTSerializable<CompoundTag> {
|
||||
class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlayer) : INBTSerializable<CompoundTag> {
|
||||
/**
|
||||
* Fired on main event bus [MinecraftForge.EVENT_BUS]
|
||||
* Fired on main event bus [NeoForge.EVENT_BUS]
|
||||
*/
|
||||
data class OnResearched(val research: AndroidResearch) : Event()
|
||||
|
||||
/**
|
||||
* Fired on main event bus [MinecraftForge.EVENT_BUS]
|
||||
* Fired on main event bus [NeoForge.EVENT_BUS]
|
||||
*/
|
||||
data class OnUnResearched(val research: AndroidResearch) : Event()
|
||||
|
||||
/**
|
||||
* Fired on main event bus [MinecraftForge.EVENT_BUS]
|
||||
* Fired on main event bus [NeoForge.EVENT_BUS]
|
||||
*/
|
||||
data class OnRefunded(val research: AndroidResearch) : Event()
|
||||
|
||||
/**
|
||||
* Fired on main event bus [MinecraftForge.EVENT_BUS]
|
||||
* Fired on main event bus [NeoForge.EVENT_BUS]
|
||||
*/
|
||||
data class GatherTooltipsEvent(val research: AndroidResearch, val tooltips: MutableList<Component>) : Event()
|
||||
|
||||
/**
|
||||
* Fired on main event bus [MinecraftForge.EVENT_BUS]
|
||||
*/
|
||||
@HasResult
|
||||
data class ConsumeResearchCost(val research: AndroidResearch, val isSimulating: Boolean) : Event()
|
||||
|
||||
val ply: Player get() = capability.ply
|
||||
|
||||
val syncher = DelegateSyncher()
|
||||
@ -84,7 +78,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
||||
result.onUnResearched(this)
|
||||
}
|
||||
|
||||
MinecraftForge.EVENT_BUS.post(OnUnResearched(this))
|
||||
NeoForge.EVENT_BUS.post(OnUnResearched(this))
|
||||
}
|
||||
|
||||
fun onResearched() {
|
||||
@ -92,7 +86,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
||||
result.onResearched(this)
|
||||
}
|
||||
|
||||
MinecraftForge.EVENT_BUS.post(OnResearched(this))
|
||||
NeoForge.EVENT_BUS.post(OnResearched(this))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,15 +102,6 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
||||
return true
|
||||
}
|
||||
|
||||
val event = ConsumeResearchCost(this, simulate)
|
||||
MinecraftForge.EVENT_BUS.post(event)
|
||||
|
||||
if (event.result == Event.Result.ALLOW) {
|
||||
return true
|
||||
} else if (event.result == Event.Result.DENY) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!simulate && !consumeResearchCost(true)) {
|
||||
return false
|
||||
}
|
||||
@ -183,7 +168,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
||||
}
|
||||
}
|
||||
|
||||
MinecraftForge.EVENT_BUS.post(OnRefunded(this))
|
||||
NeoForge.EVENT_BUS.post(OnRefunded(this))
|
||||
|
||||
return true
|
||||
}
|
||||
@ -300,7 +285,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
||||
line.addLines(this, lines)
|
||||
}
|
||||
|
||||
MinecraftForge.EVENT_BUS.post(GatherTooltipsEvent(this, lines))
|
||||
NeoForge.EVENT_BUS.post(GatherTooltipsEvent(this, lines))
|
||||
|
||||
return lines
|
||||
}
|
||||
@ -382,14 +367,14 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
||||
*/
|
||||
val screenTooltipHeader: Component get() = type.displayName
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["researched"] = isResearched
|
||||
it["tag"] = tag
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag) {
|
||||
isResearched = nbt.getBoolean("researched")
|
||||
tag = nbt.getCompound("tag")
|
||||
}
|
||||
|
@ -6,8 +6,7 @@ import net.minecraft.data.CachedOutput
|
||||
import net.minecraft.data.DataProvider
|
||||
import net.minecraft.data.PackOutput
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraftforge.data.event.GatherDataEvent
|
||||
import ru.dbotthepony.mc.otm.core.toJson
|
||||
import net.neoforged.neoforge.data.event.GatherDataEvent
|
||||
import ru.dbotthepony.mc.otm.core.toJsonStrict
|
||||
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
||||
import java.util.Collections
|
||||
|
@ -2,11 +2,12 @@ package ru.dbotthepony.mc.otm.android
|
||||
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.registries.DeferredRegister
|
||||
import net.minecraft.network.chat.ComponentSerialization
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
|
||||
@ -15,19 +16,19 @@ import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.getValue
|
||||
import ru.dbotthepony.mc.otm.core.util.formatPower
|
||||
import ru.dbotthepony.mc.otm.data.ComponentCodec
|
||||
import ru.dbotthepony.mc.otm.data.SingletonCodec
|
||||
import ru.dbotthepony.mc.otm.data.simpleCodec
|
||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||
import ru.dbotthepony.mc.otm.registry.RegistryDelegate
|
||||
|
||||
object AndroidResearchDescriptions {
|
||||
private val registrar = DeferredRegister.create(AndroidResearchDescription.registryKey, OverdriveThatMatters.MOD_ID)
|
||||
private val registrar = MDeferredRegister(AndroidResearchDescription.registryKey, OverdriveThatMatters.MOD_ID)
|
||||
|
||||
init {
|
||||
registrar.register("plain") { PlainAndroidResearchDescription }
|
||||
}
|
||||
|
||||
internal fun register(bus: IEventBus) {
|
||||
fun register(bus: IEventBus) {
|
||||
registrar.register(bus)
|
||||
}
|
||||
|
||||
@ -73,11 +74,11 @@ interface AndroidResearchDescription {
|
||||
* Type, representing raw description populator in registry
|
||||
*/
|
||||
interface Type<T : AndroidResearchDescription> {
|
||||
val codec: Codec<T>
|
||||
val codec: MapCodec<T>
|
||||
}
|
||||
|
||||
abstract class Singleton : AndroidResearchDescription, Type<Singleton> {
|
||||
override val codec = SingletonCodec(this)
|
||||
override val codec: MapCodec<Singleton> = MapCodec.unit(this)
|
||||
override val type: Type<*>
|
||||
get() = this
|
||||
}
|
||||
@ -92,8 +93,8 @@ interface AndroidResearchDescription {
|
||||
get() = this@Leveled
|
||||
}
|
||||
|
||||
override val codec: Codec<Instance> by lazy {
|
||||
RecordCodecBuilder.create {
|
||||
override val codec: MapCodec<Instance> by lazy {
|
||||
RecordCodecBuilder.mapCodec {
|
||||
it.group(Codec.INT.fieldOf("level").forGetter(Instance::level)).apply(it, ::Instance)
|
||||
}
|
||||
}
|
||||
@ -103,18 +104,16 @@ interface AndroidResearchDescription {
|
||||
val type: Type<*>
|
||||
|
||||
companion object {
|
||||
private val delegate = RegistryDelegate<Type<*>>("android_research_description") {
|
||||
disableSaving()
|
||||
}
|
||||
private val delegate = RegistryDelegate<Type<*>>("android_research_description") {}
|
||||
|
||||
val registry by delegate
|
||||
val registryKey get() = delegate.key
|
||||
|
||||
val CODEC: Codec<AndroidResearchDescription> by lazy {
|
||||
registry.codec.dispatch({ it.type }, { it.codec })
|
||||
registry.byNameCodec().dispatch({ it.type }, { it.codec })
|
||||
}
|
||||
|
||||
internal fun register(bus: IEventBus) {
|
||||
fun register(bus: IEventBus) {
|
||||
bus.addListener(delegate::build)
|
||||
}
|
||||
|
||||
@ -140,9 +139,11 @@ object PlainAndroidResearchDescription : AndroidResearchDescription.Type<PlainAn
|
||||
|
||||
fun make(line: Component) = Instance(line)
|
||||
|
||||
override val codec: Codec<Instance> by lazy {
|
||||
Codec
|
||||
.either(ComponentCodec, simpleCodec(::Instance, Instance::line, ComponentCodec))
|
||||
.xmap({ c -> c.map({ Instance(it) }, { it }) }, { c -> Either.left(c.line) })
|
||||
override val codec: MapCodec<Instance> by lazy {
|
||||
RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
ComponentSerialization.CODEC.fieldOf("line").forGetter { it.line }
|
||||
).apply(it, ::Instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,28 +7,31 @@ import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import net.minecraft.client.server.IntegratedServer
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
|
||||
import net.minecraft.util.profiling.ProfilerFiller
|
||||
import net.minecraftforge.event.AddReloadListenerEvent
|
||||
import net.minecraftforge.event.OnDatapackSyncEvent
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import net.neoforged.neoforge.event.AddReloadListenerEvent
|
||||
import net.neoforged.neoforge.event.OnDatapackSyncEvent
|
||||
import net.neoforged.neoforge.network.PacketDistributor
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.MINECRAFT_SERVER
|
||||
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.core.fromJsonStrict
|
||||
import ru.dbotthepony.mc.otm.core.fromNetwork
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.core.toNetwork
|
||||
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.network.MNetworkContext
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||
import ru.dbotthepony.mc.otm.onceServer
|
||||
import java.util.LinkedList
|
||||
import java.util.*
|
||||
|
||||
object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_android_research"), Iterable<AndroidResearchType> {
|
||||
const val DIRECTORY = "otm_android_research"
|
||||
@ -85,7 +88,7 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
|
||||
if (SERVER_IS_LIVE) {
|
||||
onceServer {
|
||||
for (ply in MINECRAFT_SERVER.playerList.players) {
|
||||
ply.matteryPlayer?.reloadResearch()
|
||||
ply.matteryPlayer.reloadResearch()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,21 +102,22 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
|
||||
val packet = SyncPacket(researchMap.values)
|
||||
|
||||
if (event.player != null) {
|
||||
GenericNetworkChannel.send(event.player!!, packet)
|
||||
PacketDistributor.sendToPlayer(event.player as ServerPlayer, packet)
|
||||
} else {
|
||||
GenericNetworkChannel.send(PacketDistributor.ALL.noArg(), packet)
|
||||
PacketDistributor.sendToAllPlayers(packet)
|
||||
}
|
||||
}
|
||||
|
||||
class SyncPacket(val collection: Collection<AndroidResearchType>) : MatteryPacket {
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
val SYNC_TYPE = CustomPacketPayload.Type<SyncPacket>(ResourceLocation(OverdriveThatMatters.MOD_ID, "research_sync"))
|
||||
val SYNC_CODEC: StreamCodec<FriendlyByteBuf, SyncPacket> = StreamCodec.ofMember(SyncPacket::write, ::readSyncPacket)
|
||||
|
||||
class SyncPacket(val collection: Collection<AndroidResearchType>) : CustomPacketPayload {
|
||||
fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeCollection(collection) { a, b -> AndroidResearchType.CODEC.toNetwork(a, b) }
|
||||
LOGGER.debug("Constructed android research registry packet, ${buff.writerIndex()} bytes in size")
|
||||
}
|
||||
|
||||
override fun play(context: MNetworkContext) {
|
||||
context.packetHandled = true
|
||||
|
||||
fun play(context: IPayloadContext) {
|
||||
if (NULLABLE_MINECRAFT_SERVER is IntegratedServer)
|
||||
return
|
||||
|
||||
@ -133,6 +137,10 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
|
||||
minecraft.player?.matteryPlayer?.reloadResearch()
|
||||
}
|
||||
}
|
||||
|
||||
override fun type(): CustomPacketPayload.Type<out CustomPacketPayload> {
|
||||
return SYNC_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
fun readSyncPacket(buff: FriendlyByteBuf): SyncPacket {
|
||||
|
@ -2,21 +2,22 @@ package ru.dbotthepony.mc.otm.android
|
||||
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.registries.DeferredRegister
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.getValue
|
||||
import ru.dbotthepony.mc.otm.data.SingletonCodec
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.registry.RegistryDelegate
|
||||
|
||||
object AndroidResearchResults {
|
||||
private val registrar = DeferredRegister.create(AndroidResearchResult.registryKey, OverdriveThatMatters.MOD_ID)
|
||||
private val registrar = MDeferredRegister(AndroidResearchResult.registryKey, OverdriveThatMatters.MOD_ID)
|
||||
|
||||
init {
|
||||
registrar.register("feature") { AndroidResearchResult.Feature.Companion }
|
||||
@ -24,7 +25,7 @@ object AndroidResearchResults {
|
||||
}
|
||||
|
||||
private object NanobotsArmorStrength : AndroidResearchResult.Singleton<NanobotsArmorStrength> {
|
||||
override val codec: Codec<NanobotsArmorStrength> = SingletonCodec(this)
|
||||
override val codec: MapCodec<NanobotsArmorStrength> = MapCodec.unit(this)
|
||||
override val type: AndroidResearchResult.Type<*>
|
||||
get() = this
|
||||
|
||||
@ -40,7 +41,7 @@ object AndroidResearchResults {
|
||||
}
|
||||
|
||||
private object NanobotsArmorSpeed : AndroidResearchResult.Singleton<NanobotsArmorSpeed> {
|
||||
override val codec: Codec<NanobotsArmorSpeed> = SingletonCodec(this)
|
||||
override val codec: MapCodec<NanobotsArmorSpeed> = MapCodec.unit(this)
|
||||
override val type: AndroidResearchResult.Type<*>
|
||||
get() = this
|
||||
|
||||
@ -58,14 +59,14 @@ object AndroidResearchResults {
|
||||
val NANOBOTS_ARMOR_STRENGTH: AndroidResearchResult.Singleton<*> by registrar.register("nanobots_armor_strength") { NanobotsArmorStrength }
|
||||
val NANOBOTS_ARMOR_SPEED: AndroidResearchResult.Singleton<*> by registrar.register("nanobots_armor_speed") { NanobotsArmorSpeed }
|
||||
|
||||
internal fun register(bus: IEventBus) {
|
||||
fun register(bus: IEventBus) {
|
||||
registrar.register(bus)
|
||||
}
|
||||
}
|
||||
|
||||
interface AndroidResearchResult {
|
||||
interface Type<T : AndroidResearchResult> {
|
||||
val codec: Codec<T>
|
||||
val codec: MapCodec<T>
|
||||
}
|
||||
|
||||
interface Singleton<T : Singleton<T>> : Type<T>, AndroidResearchResult
|
||||
@ -74,7 +75,7 @@ interface AndroidResearchResult {
|
||||
* Adds specific android feature [id] to target, does nothing if target already has specified feature
|
||||
*/
|
||||
class Feature(val id: ResourceLocation, val optional: Boolean = false) : AndroidResearchResult {
|
||||
val feature = MRegistry.ANDROID_FEATURES.getValue(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
|
||||
val feature = MRegistry.ANDROID_FEATURES.get(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
|
||||
|
||||
override val type: Type<*>
|
||||
get() = Companion
|
||||
@ -108,7 +109,7 @@ interface AndroidResearchResult {
|
||||
* Increases level of specific android feature [id] by specified amount [levels]
|
||||
*/
|
||||
class FeatureLevel(val id: ResourceLocation, val optional: Boolean = false, val levels: Int = 1) : AndroidResearchResult {
|
||||
val feature = MRegistry.ANDROID_FEATURES.getValue(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
|
||||
val feature = MRegistry.ANDROID_FEATURES.get(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
|
||||
|
||||
override val type: Type<*>
|
||||
get() = Companion
|
||||
@ -165,18 +166,16 @@ interface AndroidResearchResult {
|
||||
|
||||
companion object {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
private val delegate = RegistryDelegate<Type<*>>("android_research_result") {
|
||||
disableSaving()
|
||||
}
|
||||
private val delegate = RegistryDelegate<Type<*>>("android_research_result") {}
|
||||
|
||||
val registry by delegate
|
||||
val registryKey get() = delegate.key
|
||||
|
||||
val CODEC: Codec<AndroidResearchResult> by lazy {
|
||||
registry.codec.dispatch({ it.type }, { it.codec })
|
||||
registry.byNameCodec().dispatch({ it.type }, { it.codec })
|
||||
}
|
||||
|
||||
internal fun register(bus: IEventBus) {
|
||||
fun register(bus: IEventBus) {
|
||||
bus.addListener(delegate::build)
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,10 @@ import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.ComponentContents
|
||||
import net.minecraft.network.chat.ComponentSerialization
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.contents.TranslatableContents
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@ -18,13 +20,10 @@ import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite
|
||||
import ru.dbotthepony.mc.otm.client.render.sprites.SpriteType
|
||||
import ru.dbotthepony.mc.otm.core.collect.ListSet
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
||||
import ru.dbotthepony.mc.otm.data.ComponentCodec
|
||||
import ru.dbotthepony.mc.otm.data.JsonElementCodec
|
||||
import ru.dbotthepony.mc.otm.isClient
|
||||
import java.util.Optional
|
||||
@ -181,7 +180,7 @@ class AndroidResearchType(
|
||||
private val definedItems: List<Pair<Ingredient, Int>> = ImmutableList.copyOf(items)
|
||||
|
||||
val results: ImmutableList<AndroidResearchResult> = ImmutableList.copyOf(results)
|
||||
val items: Stream<out Pair<Ingredient, Int>> get() = definedItems.stream().filter { !it.first.isActuallyEmpty }
|
||||
val items: Stream<out Pair<Ingredient, Int>> get() = definedItems.stream().filter { !it.first.hasNoItems() }
|
||||
val description: ImmutableList<AndroidResearchDescription> = ImmutableList.copyOf(description)
|
||||
|
||||
/**
|
||||
@ -387,9 +386,9 @@ class AndroidResearchType(
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
ResourceLocation.CODEC.fieldOf("id").forGetter(AndroidResearchType::id),
|
||||
ListCodec(Reference.CODEC).fieldOf("prerequisites").forGetter(AndroidResearchType::prerequisites),
|
||||
ListCodec(Reference.CODEC).fieldOf("blockedBy").forGetter(AndroidResearchType::blockedBy),
|
||||
ListCodec(
|
||||
Codec.list(Reference.CODEC).fieldOf("prerequisites").forGetter(AndroidResearchType::prerequisites),
|
||||
Codec.list(Reference.CODEC).fieldOf("blockedBy").forGetter(AndroidResearchType::blockedBy),
|
||||
Codec.list(
|
||||
RecordCodecBuilder.create<Pair<Ingredient, Int>> {
|
||||
it.group(
|
||||
Ingredient.CODEC.fieldOf("item").forGetter { it.first },
|
||||
@ -397,13 +396,13 @@ class AndroidResearchType(
|
||||
).apply(it, ::Pair)
|
||||
}
|
||||
).fieldOf("items").forGetter { it.definedItems },
|
||||
ListCodec(AndroidResearchResult.CODEC).fieldOf("results").forGetter(AndroidResearchType::results),
|
||||
ListCodec(AndroidResearchDescription.CODEC).fieldOf("description").forGetter(AndroidResearchType::description),
|
||||
Codec.list(AndroidResearchResult.CODEC).fieldOf("results").forGetter(AndroidResearchType::results),
|
||||
Codec.list(AndroidResearchDescription.CODEC).fieldOf("description").forGetter(AndroidResearchType::description),
|
||||
Codec.intRange(0, Int.MAX_VALUE).fieldOf("experienceLevels").forGetter(AndroidResearchType::experienceLevels),
|
||||
ComponentCodec.optionalFieldOf("customName").forGetter { Optional.ofNullable(it.customName) },
|
||||
ComponentSerialization.CODEC.optionalFieldOf("customName").forGetter { Optional.ofNullable(it.customName) },
|
||||
JsonElementCodec.xmap({ it as? JsonObject ?: throw JsonSyntaxException("Not a json object: $it") }, { it }).optionalFieldOf("skinIcon").forGetter { Optional.ofNullable(it.skinIcon) },
|
||||
ForgeRegistries.ITEMS.codec.optionalFieldOf("itemIcon").forGetter { Optional.ofNullable(it.itemIcon) },
|
||||
ComponentCodec.optionalFieldOf("iconTextValue").forGetter { Optional.ofNullable(it.iconTextValue) },
|
||||
BuiltInRegistries.ITEM.byNameCodec().optionalFieldOf("itemIcon").forGetter { Optional.ofNullable(it.itemIcon) },
|
||||
ComponentSerialization.CODEC.optionalFieldOf("iconTextValue").forGetter { Optional.ofNullable(it.iconTextValue) },
|
||||
).apply(it, ::AndroidResearchType)
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package ru.dbotthepony.mc.otm.android
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
|
||||
abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: MatteryPlayerCapability) : AndroidFeature(type, android) {
|
||||
abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: MatteryPlayer) : AndroidFeature(type, android) {
|
||||
var isActive by syncher.boolean(setter = setter@{ access, value ->
|
||||
if (value != access.get()) {
|
||||
access.accept(value)
|
||||
@ -52,15 +53,15 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma
|
||||
// but it doesn't seem to cause issues?
|
||||
abstract fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor = RGBAColor.WHITE)
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
return super.serializeNBT().also {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return super.serializeNBT(registry).also {
|
||||
it["isActive"] = isActive
|
||||
it["cooldown"] = cooldown
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
super.deserializeNBT(nbt)
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag) {
|
||||
super.deserializeNBT(registry, nbt)
|
||||
isActive = nbt.getBoolean("isActive")
|
||||
cooldown = nbt.getInt("cooldown")
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package ru.dbotthepony.mc.otm.android.feature
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import java.util.*
|
||||
|
||||
class AttackBoostFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.ATTACK_BOOST, android) {
|
||||
class AttackBoostFeature(android: MatteryPlayer) : AndroidFeature(AndroidFeatures.ATTACK_BOOST, android) {
|
||||
override fun applyModifiers() {
|
||||
val modifier = ply.getAttribute(Attributes.ATTACK_DAMAGE)
|
||||
|
||||
|
@ -20,22 +20,23 @@ import net.minecraft.world.phys.HitResult
|
||||
import net.minecraft.world.phys.shapes.BooleanOp
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraftforge.client.event.RenderLevelStageEvent
|
||||
import net.minecraftforge.event.ForgeEventFactory
|
||||
import net.minecraftforge.event.entity.living.LivingDeathEvent
|
||||
import net.neoforged.neoforge.client.event.RenderLevelStageEvent
|
||||
import net.neoforged.neoforge.event.EventHooks
|
||||
import net.neoforged.neoforge.event.entity.living.LivingDeathEvent
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||
import ru.dbotthepony.mc.otm.client.render.linesIgnoreZRenderType
|
||||
import ru.dbotthepony.mc.otm.client.render.sprites.sprite
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.core.genericPositions
|
||||
import ru.dbotthepony.mc.otm.core.holder
|
||||
import ru.dbotthepony.mc.otm.core.isFall
|
||||
@ -55,7 +56,7 @@ import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
|
||||
import java.util.*
|
||||
import kotlin.math.sin
|
||||
|
||||
class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiveFeature(AndroidFeatures.ENDER_TELEPORTER, capability) {
|
||||
class EnderTeleporterFeature(capability: MatteryPlayer) : AndroidActiveFeature(AndroidFeatures.ENDER_TELEPORTER, capability) {
|
||||
var lastTeleport = 0
|
||||
private set
|
||||
|
||||
@ -299,7 +300,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
|
||||
val (blockPos) = trace()
|
||||
blockPos ?: return false
|
||||
|
||||
val event = ForgeEventFactory.onEnderTeleport(ply, blockPos.x + 0.5, blockPos.y.toDouble(), blockPos.z + 0.5)
|
||||
val event = EventHooks.onEnderTeleport(ply, blockPos.x + 0.5, blockPos.y.toDouble(), blockPos.z + 0.5)
|
||||
|
||||
if (event.isCanceled) {
|
||||
(ply as ServerPlayer).connection.send(ClientboundSoundEntityPacket(SoundEvents.ITEM_BREAK.holder, SoundSource.PLAYERS, ply, 0.3f, 0.5f, ply.level().random.nextLong()))
|
||||
|
@ -1,31 +1,26 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier
|
||||
import net.minecraftforge.common.ForgeMod
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import java.util.*
|
||||
|
||||
class ExtendedReachFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.EXTENDED_REACH, android) {
|
||||
class ExtendedReachFeature(android: MatteryPlayer) : AndroidFeature(AndroidFeatures.EXTENDED_REACH, android) {
|
||||
override fun applyModifiers() {
|
||||
if (!ForgeMod.BLOCK_REACH.isPresent)
|
||||
return
|
||||
val reach = ply.getAttribute(Attributes.BLOCK_INTERACTION_RANGE) ?: return
|
||||
|
||||
val reach = ply.getAttribute(ForgeMod.BLOCK_REACH.get()) ?: return
|
||||
|
||||
reach.removePermanentModifier(MODIFIER_ID)
|
||||
reach.addPermanentModifier(AttributeModifier(MODIFIER_ID, type.displayName.toString(), level + 1.0, AttributeModifier.Operation.ADDITION))
|
||||
reach.removeModifier(MODIFIER_ID)
|
||||
reach.addPermanentModifier(AttributeModifier(MODIFIER_ID, level + 1.0, AttributeModifier.Operation.ADD_VALUE))
|
||||
}
|
||||
|
||||
override fun removeModifiers() {
|
||||
if (!ForgeMod.BLOCK_REACH.isPresent)
|
||||
return
|
||||
|
||||
ply.getAttribute(ForgeMod.BLOCK_REACH.get())?.removePermanentModifier(MODIFIER_ID)
|
||||
ply.getAttribute(Attributes.BLOCK_INTERACTION_RANGE)?.removeModifier(MODIFIER_ID)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MODIFIER_ID = UUID.fromString("4a3fae46-47a8-a03f-857d-f5c2b2c8f2f2")
|
||||
private val MODIFIER_ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "android_extended_reach")
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,16 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraftforge.event.entity.living.LivingAttackEvent
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.isFall
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
|
||||
|
||||
class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.FALL_DAMPENERS, capability) {
|
||||
override fun onHurt(event: LivingHurtEvent) {
|
||||
class FallDampenersFeature(capability: MatteryPlayer) : AndroidFeature(AndroidFeatures.FALL_DAMPENERS, capability) {
|
||||
override fun onHurt(event: LivingIncomingDamageEvent) {
|
||||
if (event.source.isFall) {
|
||||
val reduction = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * (level + 1)).toFloat().coerceIn(0f, 1f)
|
||||
val flat = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * (level + 1)).toFloat().coerceIn(0f, Float.MAX_VALUE)
|
||||
@ -35,15 +27,4 @@ class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttack(event: LivingAttackEvent) {
|
||||
if (event.source.isFall) {
|
||||
val reduction = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * (level + 1)).toFloat().coerceIn(0f, 1f)
|
||||
val flat = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * (level + 1)).toFloat().coerceIn(0f, Float.MAX_VALUE)
|
||||
|
||||
if (reduction >= 1f || event.amount <= flat) {
|
||||
event.isCanceled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,29 @@ package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.neoforged.neoforge.network.PacketDistributor
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
|
||||
import ru.dbotthepony.mc.otm.core.math.minus
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.core.position
|
||||
import ru.dbotthepony.mc.otm.core.math.times
|
||||
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.network.MNetworkContext
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import java.util.UUID
|
||||
import java.util.WeakHashMap
|
||||
@ -34,8 +38,8 @@ private data class SharedItemEntityData(val owner: UUID? = null, val age: Int =
|
||||
|
||||
private val datatable = WeakHashMap<ItemEntity, SharedItemEntityData>()
|
||||
|
||||
class ItemEntityDataPacket(val itemUUID: Int, val owner: UUID? = null, val age: Int = 0, val lifespan: Int = 0, val hasPickupDelay: Boolean = true) : MatteryPacket {
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
class ItemEntityDataPacket(val itemUUID: Int, val owner: UUID? = null, val age: Int = 0, val lifespan: Int = 0, val hasPickupDelay: Boolean = true) : CustomPacketPayload {
|
||||
fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeVarInt(itemUUID)
|
||||
buff.writeBoolean(owner != null)
|
||||
if (owner != null) buff.writeUUID(owner)
|
||||
@ -44,20 +48,27 @@ class ItemEntityDataPacket(val itemUUID: Int, val owner: UUID? = null, val age:
|
||||
buff.writeBoolean(hasPickupDelay)
|
||||
}
|
||||
|
||||
override fun play(context: MNetworkContext) {
|
||||
fun play(context: IPayloadContext) {
|
||||
val level = minecraft.player?.level() as ClientLevel? ?: return
|
||||
val entity = level.getEntity(itemUUID) as ItemEntity? ?: return
|
||||
datatable[entity] = SharedItemEntityData(owner, age, lifespan, hasPickupDelay)
|
||||
}
|
||||
|
||||
override fun type(): CustomPacketPayload.Type<out CustomPacketPayload> {
|
||||
return TYPE
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TYPE = CustomPacketPayload.Type<ItemEntityDataPacket>(ResourceLocation(OverdriveThatMatters.MOD_ID, "item_entity_data"))
|
||||
val CODEC: StreamCodec<FriendlyByteBuf, ItemEntityDataPacket> = StreamCodec.ofMember(ItemEntityDataPacket::write, ::read)
|
||||
|
||||
fun read(buff: FriendlyByteBuf): ItemEntityDataPacket {
|
||||
return ItemEntityDataPacket(buff.readVarInt(), if (buff.readBoolean()) buff.readUUID() else null, buff.readVarInt(), buff.readVarInt(), buff.readBoolean())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.ITEM_MAGNET, capability) {
|
||||
class ItemMagnetFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(AndroidFeatures.ITEM_MAGNET, capability) {
|
||||
private data class ItemPos(var position: Vector, var ticksSinceActivity: Int)
|
||||
private val rememberPositions = WeakHashMap<ItemEntity, ItemPos>()
|
||||
|
||||
@ -79,7 +90,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
|
||||
ent as ItemEntity
|
||||
|
||||
if (server) {
|
||||
GenericNetworkChannel.send(ply, ItemEntityDataPacket(ent.id, ent.owner?.uuid, ent.age, ent.lifespan, ent.hasPickUpDelay()))
|
||||
PacketDistributor.sendToPlayer(ply as ServerPlayer, ItemEntityDataPacket(ent.id, ent.owner?.uuid, ent.age, ent.lifespan, ent.hasPickUpDelay()))
|
||||
|
||||
if (!serverPredicate.test(ent)) {
|
||||
continue
|
||||
|
@ -1,57 +1,26 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.neoforged.neoforge.network.PacketDistributor
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.mc.otm.config.ClientConfig
|
||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.network.MNetworkContext
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket
|
||||
import ru.dbotthepony.mc.otm.network.TriggerJumpBoostPacket
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.registry.MSoundEvents
|
||||
|
||||
object TriggerJumpBoostPacket : MatteryPacket {
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
// no op
|
||||
}
|
||||
|
||||
override fun play(context: MNetworkContext) {
|
||||
val mattery = context.sender?.matteryPlayer ?: return
|
||||
|
||||
if (!mattery.isAndroid)
|
||||
return
|
||||
|
||||
val feature = mattery.getFeature(AndroidFeatures.JUMP_BOOST) ?: return
|
||||
|
||||
if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, false)) {
|
||||
feature.putOnCooldown()
|
||||
|
||||
context.sender.level().playSound(
|
||||
context.sender, context.sender,
|
||||
MSoundEvents.ANDROID_JUMP_BOOST, SoundSource.PLAYERS,
|
||||
1f, 1f
|
||||
)
|
||||
|
||||
GenericNetworkChannel.makeSmoke(context.sender, context.sender.x, context.sender.y, context.sender.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.JUMP_BOOST, capability) {
|
||||
class JumpBoostFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(AndroidFeatures.JUMP_BOOST, capability) {
|
||||
private var tickCooldownClient = false
|
||||
|
||||
override val maxCooldown: Int
|
||||
@ -80,7 +49,7 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
if (isActive && cooldown <= 0 && old != lastGround && !lastGround && isJumping && isShifting && ply.xRot <= ClientConfig.JUMP_BOOST_LOOK_ANGLE && android.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, true)) {
|
||||
ply.deltaMovement += Vector(0.0, AndroidConfig.JumpBoost.POWER * (level + 1) / 20.0, 0.0)
|
||||
putOnCooldown()
|
||||
MatteryPlayerNetworkChannel.sendToServer(TriggerJumpBoostPacket)
|
||||
PacketDistributor.sendToServer(TriggerJumpBoostPacket)
|
||||
|
||||
ply.level().playSound(
|
||||
ply, ply,
|
||||
|
@ -4,36 +4,38 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import java.util.*
|
||||
|
||||
class LimbOverclockingFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.LIMB_OVERCLOCKING, android) {
|
||||
class LimbOverclockingFeature(android: MatteryPlayer) : AndroidFeature(AndroidFeatures.LIMB_OVERCLOCKING, android) {
|
||||
override fun applyModifiers() {
|
||||
val speed = ply.getAttribute(Attributes.MOVEMENT_SPEED)
|
||||
|
||||
if (speed != null) {
|
||||
speed.removePermanentModifier(MODIFIER_ID)
|
||||
speed.addPermanentModifier(AttributeModifier(MODIFIER_ID, type.displayName.toString(), (level + 1) * 0.08, AttributeModifier.Operation.MULTIPLY_TOTAL))
|
||||
speed.removeModifier(MODIFIER_ID)
|
||||
speed.addPermanentModifier(AttributeModifier(MODIFIER_ID,(level + 1) * 0.08, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL))
|
||||
}
|
||||
|
||||
val attackSpeed = ply.getAttribute(Attributes.ATTACK_SPEED)
|
||||
|
||||
if (attackSpeed != null) {
|
||||
attackSpeed.removePermanentModifier(MODIFIER_ID)
|
||||
attackSpeed.addPermanentModifier(AttributeModifier(MODIFIER_ID, type.displayName.toString(), (level + 1) * 0.06, AttributeModifier.Operation.MULTIPLY_TOTAL))
|
||||
attackSpeed.removeModifier(MODIFIER_ID)
|
||||
attackSpeed.addPermanentModifier(AttributeModifier(MODIFIER_ID, (level + 1) * 0.06, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL))
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeModifiers() {
|
||||
ply.getAttribute(Attributes.MOVEMENT_SPEED)?.removePermanentModifier(MODIFIER_ID)
|
||||
ply.getAttribute(Attributes.ATTACK_SPEED)?.removePermanentModifier(MODIFIER_ID)
|
||||
ply.getAttribute(Attributes.MOVEMENT_SPEED)?.removeModifier(MODIFIER_ID)
|
||||
ply.getAttribute(Attributes.ATTACK_SPEED)?.removeModifier(MODIFIER_ID)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MODIFIER_ID = UUID.fromString("4a3fae46-e57b-4e20-857d-f5c2b2c8f2f2")
|
||||
private val MODIFIER_ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking")
|
||||
|
||||
@JvmStatic
|
||||
fun getBrushCooldown(entity: LivingEntity): Int {
|
||||
|
@ -1,12 +1,13 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
||||
import ru.dbotthepony.mc.otm.core.isBypassArmor
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
@ -17,7 +18,7 @@ import ru.dbotthepony.mc.otm.onceServer
|
||||
import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) {
|
||||
class NanobotsArmorFeature(android: MatteryPlayer) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) {
|
||||
var strength by syncher.int(
|
||||
setter = setter@{ access, value -> access.accept(value.coerceIn(0 .. 3)) }
|
||||
)
|
||||
@ -42,7 +43,7 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHurt(event: LivingHurtEvent) {
|
||||
override fun onHurt(event: LivingIncomingDamageEvent) {
|
||||
ticksPassed = 0
|
||||
|
||||
if (!event.source.isBypassArmor && layers > 0) {
|
||||
@ -69,8 +70,8 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
return super.serializeNBT().also {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return super.serializeNBT(registry).also {
|
||||
it["ticksPassed"] = ticksPassed
|
||||
it["layers"] = layers
|
||||
it["strength"] = strength
|
||||
@ -78,8 +79,8 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
super.deserializeNBT(nbt)
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag) {
|
||||
super.deserializeNBT(registry, nbt)
|
||||
ticksPassed = nbt.getInt("ticksPassed")
|
||||
layers = nbt.getInt("layers")
|
||||
strength = nbt.getInt("strength")
|
||||
|
@ -1,18 +1,19 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.level.GameRules
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.registry.StatNames
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class NanobotsRegenerationFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_REGENERATION, android) {
|
||||
class NanobotsRegenerationFeature(android: MatteryPlayer) : AndroidFeature(AndroidFeatures.NANOBOTS_REGENERATION, android) {
|
||||
private var ticksPassed = 0
|
||||
private var healTicks = 0
|
||||
|
||||
@ -41,22 +42,22 @@ class NanobotsRegenerationFeature(android: MatteryPlayerCapability) : AndroidFea
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHurt(event: LivingHurtEvent) {
|
||||
override fun onHurt(event: LivingIncomingDamageEvent) {
|
||||
if (event.amount > 0f) {
|
||||
ticksPassed = 0
|
||||
healTicks = 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
return super.serializeNBT().also {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return super.serializeNBT(registry).also {
|
||||
it["ticksPassed"] = ticksPassed
|
||||
it["healTicks"] = healTicks
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
super.deserializeNBT(nbt)
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag) {
|
||||
super.deserializeNBT(registry, nbt)
|
||||
ticksPassed = nbt.getInt("ticksPassed")
|
||||
healTicks = nbt.getInt("healTicks")
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
|
||||
class NightVisionFeature(android: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.NIGHT_VISION, android) {
|
||||
class NightVisionFeature(android: MatteryPlayer) : AndroidSwitchableFeature(AndroidFeatures.NIGHT_VISION, android) {
|
||||
override val allowToSwitchByPlayerWhileSpectator: Boolean
|
||||
get() = true
|
||||
|
||||
|
@ -2,13 +2,16 @@ package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceArraySet
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.monster.warden.Warden
|
||||
import net.neoforged.neoforge.network.PacketDistributor
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext
|
||||
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
@ -25,11 +28,8 @@ import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.core.math.roundToIntVector
|
||||
import ru.dbotthepony.mc.otm.core.math.times
|
||||
import ru.dbotthepony.mc.otm.core.position
|
||||
import ru.dbotthepony.mc.otm.network.MNetworkContext
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.network.ShockwaveEffectPacket
|
||||
import ru.dbotthepony.mc.otm.onceServer
|
||||
import ru.dbotthepony.mc.otm.network.TriggerShockwavePacket
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.registry.MDamageTypes
|
||||
import ru.dbotthepony.mc.otm.registry.MSoundEvents
|
||||
@ -39,23 +39,7 @@ import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object TriggerShockwavePacket : MatteryPacket {
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
// no op
|
||||
}
|
||||
|
||||
override fun play(context: MNetworkContext) {
|
||||
val shockwave = context.sender?.matteryPlayer?.getFeature(AndroidFeatures.SHOCKWAVE) ?: return
|
||||
|
||||
if (!shockwave.isOnCooldown && shockwave.isActive && shockwave.airTicks > 0) {
|
||||
onceServer { // delay by one tick so player update its position as well
|
||||
shockwave.shockwave()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.SHOCKWAVE, capability) {
|
||||
class ShockwaveFeature(capability: MatteryPlayer) : AndroidSwitchableFeature(AndroidFeatures.SHOCKWAVE, capability) {
|
||||
override val maxCooldown: Int
|
||||
get() = AndroidConfig.Shockwave.COOLDOWN
|
||||
|
||||
@ -91,7 +75,7 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ShockwaveTrigger.trigger(ply as ServerPlayer)
|
||||
MatteryPlayerNetworkChannel.sendTrackingAndSelf(ply, ShockwaveEffectPacket(ply.position))
|
||||
PacketDistributor.sendToPlayersTrackingEntityAndSelf(ply, ShockwaveEffectPacket(ply.position))
|
||||
|
||||
ply.level().playSound(
|
||||
null,
|
||||
@ -204,7 +188,7 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
// I HATE SELF-UPDATING PLAYERS
|
||||
// fix "bug" where shockwave doesn't trigger even when player is falling faster than orbiting satellite
|
||||
putOnCooldown()
|
||||
MatteryPlayerNetworkChannel.sendToServer(TriggerShockwavePacket)
|
||||
PacketDistributor.sendToServer(TriggerShockwavePacket)
|
||||
} else {
|
||||
shockwave()
|
||||
}
|
||||
|
@ -1,31 +1,29 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier
|
||||
import net.minecraftforge.common.ForgeMod
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import java.util.*
|
||||
|
||||
class StepAssistFeature(android: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.STEP_ASSIST, android) {
|
||||
class StepAssistFeature(android: MatteryPlayer) : AndroidSwitchableFeature(AndroidFeatures.STEP_ASSIST, android) {
|
||||
override fun applyModifiers() {
|
||||
if (!ForgeMod.STEP_HEIGHT_ADDITION.isPresent || !isActive)
|
||||
if (!isActive)
|
||||
return
|
||||
|
||||
val reach = ply.getAttribute(ForgeMod.STEP_HEIGHT_ADDITION.get()) ?: return
|
||||
val reach = ply.getAttribute(Attributes.STEP_HEIGHT) ?: return
|
||||
|
||||
reach.removeModifier(MODIFIER_ID)
|
||||
reach.addPermanentModifier(AttributeModifier(MODIFIER_ID, type.displayName.toString(), (level + 1) * 0.5, AttributeModifier.Operation.ADDITION))
|
||||
reach.addPermanentModifier(AttributeModifier(MODIFIER_ID, (level + 1) * 0.5, AttributeModifier.Operation.ADD_VALUE))
|
||||
}
|
||||
|
||||
override fun removeModifiers() {
|
||||
if (!ForgeMod.STEP_HEIGHT_ADDITION.isPresent)
|
||||
return
|
||||
|
||||
ply.getAttribute(ForgeMod.STEP_HEIGHT_ADDITION.get())?.removeModifier(MODIFIER_ID)
|
||||
ply.getAttribute(Attributes.STEP_HEIGHT)?.removeModifier(MODIFIER_ID)
|
||||
}
|
||||
|
||||
private var isShiftKeyDown = false
|
||||
@ -59,6 +57,6 @@ class StepAssistFeature(android: MatteryPlayerCapability) : AndroidSwitchableFea
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MODIFIER_ID = UUID.fromString("4a3fae46-47a8-a03f-857d-f5c2b2c8f2f4")
|
||||
private val MODIFIER_ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "step_assist_feature")
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,30 @@
|
||||
package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier
|
||||
import net.minecraftforge.common.ForgeMod
|
||||
import net.neoforged.neoforge.common.NeoForgeMod
|
||||
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
|
||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import java.util.*
|
||||
|
||||
class SwimBoostersFeature(android: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.SWIM_BOOSTERS, android) {
|
||||
class SwimBoostersFeature(android: MatteryPlayer) : AndroidSwitchableFeature(AndroidFeatures.SWIM_BOOSTERS, android) {
|
||||
override fun applyModifiers() {
|
||||
if (!ForgeMod.SWIM_SPEED.isPresent || !isActive)
|
||||
if (!isActive)
|
||||
return
|
||||
|
||||
val attr = ply.getAttribute(ForgeMod.SWIM_SPEED.get()) ?: return
|
||||
val attr = ply.getAttribute(NeoForgeMod.SWIM_SPEED) ?: return
|
||||
|
||||
attr.removeModifier(MODIFIER_ID)
|
||||
attr.addPermanentModifier(AttributeModifier(MODIFIER_ID, type.displayName.toString(), (level + 1) * AndroidConfig.SWIM_BOOSTERS, AttributeModifier.Operation.ADDITION))
|
||||
attr.addPermanentModifier(AttributeModifier(MODIFIER_ID, (level + 1) * AndroidConfig.SWIM_BOOSTERS, AttributeModifier.Operation.ADD_VALUE))
|
||||
}
|
||||
|
||||
override fun removeModifiers() {
|
||||
if (!ForgeMod.SWIM_SPEED.isPresent)
|
||||
return
|
||||
|
||||
ply.getAttribute(ForgeMod.SWIM_SPEED.get())?.removeModifier(MODIFIER_ID)
|
||||
ply.getAttribute(NeoForgeMod.SWIM_SPEED)?.removeModifier(MODIFIER_ID)
|
||||
}
|
||||
|
||||
override fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor) {
|
||||
@ -34,6 +32,6 @@ class SwimBoostersFeature(android: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MODIFIER_ID = UUID.fromString("4a3ffa46-47a8-a03f-857d-f5c2b2c8f2f6")
|
||||
private val MODIFIER_ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "swim_boosters_feature")
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.TooltipFlag
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
@ -42,7 +43,6 @@ import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
|
||||
import ru.dbotthepony.mc.otm.core.math.component1
|
||||
import ru.dbotthepony.mc.otm.core.math.component2
|
||||
import ru.dbotthepony.mc.otm.core.math.component3
|
||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||
import ru.dbotthepony.mc.otm.once
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.function.Function
|
||||
@ -117,13 +117,11 @@ open class MatteryBlock(properties: Properties = DEFAULT_PROPERTIES) : Block(pro
|
||||
return getShapeForEachState(ArrayList(stateDefinition.properties), mapper)
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION")
|
||||
override fun use(
|
||||
override fun useWithoutItem(
|
||||
blockState: BlockState,
|
||||
level: Level,
|
||||
blockPos: BlockPos,
|
||||
ply: Player,
|
||||
hand: InteractionHand,
|
||||
blockHitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
if (this is EntityBlock && !level.isClientSide) {
|
||||
@ -138,8 +136,7 @@ open class MatteryBlock(properties: Properties = DEFAULT_PROPERTIES) : Block(pro
|
||||
if (this is EntityBlock && level.isClientSide)
|
||||
return InteractionResult.SUCCESS
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
return super.use(blockState, level, blockPos, ply, hand, blockHitResult)
|
||||
return super.useWithoutItem(blockState, level, blockPos, ply, blockHitResult)
|
||||
}
|
||||
|
||||
override fun animateTick(blockState: BlockState, level: Level, blockPos: BlockPos, random: RandomSource) {
|
||||
@ -261,9 +258,14 @@ open class MatteryBlock(properties: Properties = DEFAULT_PROPERTIES) : Block(pro
|
||||
}
|
||||
}
|
||||
|
||||
override fun appendHoverText(itemStack: ItemStack, blockAccessor: BlockGetter?, components: MutableList<Component>, tooltipType: TooltipFlag) {
|
||||
super.appendHoverText(itemStack, blockAccessor, components, tooltipType)
|
||||
tooltips.assemble(itemStack, components)
|
||||
override fun appendHoverText(
|
||||
itemStack: ItemStack,
|
||||
p_339606_: Item.TooltipContext,
|
||||
components: MutableList<Component>,
|
||||
tooltipType: TooltipFlag
|
||||
) {
|
||||
super.appendHoverText(itemStack, p_339606_, components, tooltipType)
|
||||
tooltips.assemble(itemStack, p_339606_, components)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -14,7 +14,7 @@ import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import net.minecraftforge.fluids.FluidUtil
|
||||
import net.neoforged.neoforge.fluids.FluidUtil
|
||||
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.getShapeForEachState
|
||||
@ -54,12 +54,11 @@ class FluidTankBlock : RotatableMatteryBlock(DEFAULT_MACHINE_PROPERTIES), Entity
|
||||
return shapes[state]!!
|
||||
}
|
||||
|
||||
override fun getLightEmission(state: BlockState?, level: BlockGetter?, pos: BlockPos?): Int {
|
||||
override fun getLightEmission(state: BlockState, level: BlockGetter, pos: BlockPos): Int {
|
||||
if (pos == BlockPos.ZERO) return 15
|
||||
|
||||
val lightLevel = super.getLightEmission(state, level, pos)
|
||||
|
||||
val tile = level?.getExistingBlockEntity(pos) ?: lightLevel
|
||||
val tile = level.getBlockEntity(pos)
|
||||
|
||||
if (tile is FluidTankBlockEntity) {
|
||||
val fluid = tile.fluid.fluid
|
||||
|
@ -3,7 +3,9 @@ package ru.dbotthepony.mc.otm.block.decorative
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.ItemInteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
@ -13,7 +15,7 @@ import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.material.MapColor
|
||||
import net.minecraft.world.level.material.PushReaction
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraftforge.fluids.FluidUtil
|
||||
import net.neoforged.neoforge.fluids.FluidUtil
|
||||
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.decorative.InfiniteWaterSourceBlockEntity
|
||||
|
||||
@ -22,13 +24,20 @@ class InfiniteWaterSourceBlock : RotatableMatteryBlock(Properties.of().destroyTi
|
||||
return InfiniteWaterSourceBlockEntity(p_153215_, p_153216_)
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION")
|
||||
override fun use(blockState: BlockState, level: Level, blockPos: BlockPos, ply: Player, hand: InteractionHand, blockHitResult: BlockHitResult): InteractionResult {
|
||||
if (FluidUtil.interactWithFluidHandler(ply, hand, level, blockPos, blockHitResult.direction)) {
|
||||
return InteractionResult.sidedSuccess(level.isClientSide)
|
||||
override fun useItemOn(
|
||||
p_316304_: ItemStack,
|
||||
p_316362_: BlockState,
|
||||
p_316459_: Level,
|
||||
p_316366_: BlockPos,
|
||||
p_316132_: Player,
|
||||
p_316595_: InteractionHand,
|
||||
p_316140_: BlockHitResult
|
||||
): ItemInteractionResult {
|
||||
if (FluidUtil.interactWithFluidHandler(p_316132_, p_316595_, p_316459_, p_316366_, p_316140_.direction)) {
|
||||
return ItemInteractionResult.sidedSuccess(p_316459_.isClientSide)
|
||||
}
|
||||
|
||||
return super.use(blockState, level, blockPos, ply, hand, blockHitResult)
|
||||
return super.useItemOn(p_316304_, p_316362_, p_316459_, p_316366_, p_316132_, p_316595_, p_316140_)
|
||||
}
|
||||
|
||||
override fun <T : BlockEntity> getTicker(p_153212_: Level, p_153213_: BlockState, p_153214_: BlockEntityType<T>): BlockEntityTicker<T>? {
|
||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.block.decorative
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.TooltipFlag
|
||||
@ -122,11 +123,11 @@ class LaboratoryLamp(val invertRedstone: Boolean) : Block(Properties.of().mapCol
|
||||
|
||||
override fun appendHoverText(
|
||||
p_49816_: ItemStack,
|
||||
p_49817_: BlockGetter?,
|
||||
p_339606_: Item.TooltipContext,
|
||||
p_49818_: MutableList<Component>,
|
||||
p_49819_: TooltipFlag
|
||||
) {
|
||||
super.appendHoverText(p_49816_, p_49817_, p_49818_, p_49819_)
|
||||
super.appendHoverText(p_49816_, p_339606_, p_49818_, p_49819_)
|
||||
p_49818_.add(TranslatableComponent("${MBlocks.LABORATORY_LAMP.descriptionId}.description").withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,9 @@ package ru.dbotthepony.mc.otm.block.decorative
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.ItemInteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
@ -11,7 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraftforge.fluids.FluidUtil
|
||||
import net.neoforged.neoforge.fluids.FluidUtil
|
||||
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity
|
||||
|
||||
@ -20,13 +22,20 @@ class PainterBlock : RotatableMatteryBlock(DEFAULT_MACHINE_PROPERTIES), EntityBl
|
||||
return PainterBlockEntity(p_153215_, p_153216_)
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION")
|
||||
override fun use(blockState: BlockState, level: Level, blockPos: BlockPos, ply: Player, hand: InteractionHand, blockHitResult: BlockHitResult): InteractionResult {
|
||||
override fun useItemOn(
|
||||
p_316304_: ItemStack,
|
||||
blockState: BlockState,
|
||||
level: Level,
|
||||
blockPos: BlockPos,
|
||||
ply: Player,
|
||||
hand: InteractionHand,
|
||||
blockHitResult: BlockHitResult
|
||||
): ItemInteractionResult {
|
||||
if (FluidUtil.interactWithFluidHandler(ply, hand, level, blockPos, blockHitResult.direction)) {
|
||||
return InteractionResult.sidedSuccess(level.isClientSide)
|
||||
return ItemInteractionResult.sidedSuccess(level.isClientSide)
|
||||
}
|
||||
|
||||
return super.use(blockState, level, blockPos, ply, hand, blockHitResult)
|
||||
return super.useItemOn(p_316304_, blockState, level, blockPos, ply, hand, blockHitResult)
|
||||
}
|
||||
|
||||
override fun <T : BlockEntity?> getTicker(p_153212_: Level, p_153213_: BlockState, p_153214_: BlockEntityType<T>): BlockEntityTicker<T>? {
|
||||
|
@ -1,13 +1,14 @@
|
||||
package ru.dbotthepony.mc.otm.block.decorative
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.TooltipFlag
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BasePressurePlateBlock
|
||||
import net.minecraft.world.level.block.Block
|
||||
@ -18,7 +19,6 @@ import net.minecraft.world.level.block.state.properties.BlockSetType
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
||||
import ru.dbotthepony.mc.otm.core.TooltipList
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.collect.iteratorOf
|
||||
import ru.dbotthepony.mc.otm.core.get
|
||||
|
||||
class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of().mapColor(color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops().forceSolidOn().noCollission(), BlockSetType.IRON) {
|
||||
@ -26,12 +26,12 @@ class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properti
|
||||
|
||||
override fun appendHoverText(
|
||||
itemStack: ItemStack,
|
||||
level: BlockGetter?,
|
||||
context: Item.TooltipContext,
|
||||
lines: MutableList<Component>,
|
||||
tooltipType: TooltipFlag
|
||||
) {
|
||||
super.appendHoverText(itemStack, level, lines, tooltipType)
|
||||
tooltips.assemble(itemStack, lines)
|
||||
super.appendHoverText(itemStack, context, lines, tooltipType)
|
||||
tooltips.assemble(itemStack, context, lines)
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.block.entity
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.DoubleTag
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@ -10,9 +11,9 @@ import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable
|
||||
import net.neoforged.neoforge.fluids.FluidStack
|
||||
import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
||||
import ru.dbotthepony.mc.otm.block.INeighbourChangeListener
|
||||
import ru.dbotthepony.mc.otm.block.entity.tech.EssenceStorageBlockEntity
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
@ -98,11 +99,11 @@ class ExperienceStorage(val maxExperience: DoubleSupplier = DoubleSupplier { Dou
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeNBT(): DoubleTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): DoubleTag {
|
||||
return DoubleTag.valueOf(experience)
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: DoubleTag?) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: DoubleTag?) {
|
||||
experience = (nbt?.asDouble ?: 0.0).coerceAtLeast(0.0)
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,11 @@ package ru.dbotthepony.mc.otm.block.entity
|
||||
import com.mojang.datafixers.Products
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
@ -17,7 +18,6 @@ import ru.dbotthepony.mc.otm.core.math.weakGreaterThan
|
||||
import ru.dbotthepony.mc.otm.core.math.weakLessThan
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||
import ru.dbotthepony.mc.otm.data.minRange
|
||||
|
||||
private fun isReason(status: Any?, reason: Any) = status == null || status == reason
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
@ -325,12 +325,12 @@ abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) :
|
||||
OBSERVING
|
||||
}
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return CompoundTag().also { nbt ->
|
||||
nbt["WorkTicks"] = workTicks
|
||||
|
||||
currentJob?.let {
|
||||
codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map(
|
||||
codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).mapOrElse(
|
||||
{
|
||||
nbt["Job"] = it
|
||||
},
|
||||
@ -342,14 +342,14 @@ abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) :
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag?) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag?) {
|
||||
nbt ?: return
|
||||
|
||||
workTicks = nbt.getDouble("WorkTicks")
|
||||
currentJob = null
|
||||
|
||||
if ("Job" in nbt) {
|
||||
codec.decode(NbtOps.INSTANCE, nbt["Job"]!!).get().map(
|
||||
codec.decode(NbtOps.INSTANCE, nbt["Job"]!!).mapOrElse(
|
||||
{
|
||||
currentJob = it.first
|
||||
},
|
||||
|
@ -10,6 +10,7 @@ import it.unimi.dsi.fastutil.objects.Reference2IntArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup.Provider
|
||||
import net.minecraft.core.SectionPos
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
@ -26,15 +27,15 @@ import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.chunk.LevelChunk
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.common.capabilities.Capability
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.common.util.LazyOptional
|
||||
import net.minecraftforge.energy.IEnergyStorage
|
||||
import net.minecraftforge.event.TickEvent.LevelTickEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent
|
||||
import net.minecraftforge.event.level.ChunkWatchEvent
|
||||
import net.minecraftforge.event.level.LevelEvent
|
||||
import net.minecraftforge.event.server.ServerStoppingEvent
|
||||
import net.neoforged.neoforge.capabilities.BlockCapability
|
||||
import net.neoforged.neoforge.capabilities.BlockCapabilityCache
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerEvent
|
||||
import net.neoforged.neoforge.event.level.ChunkWatchEvent
|
||||
import net.neoforged.neoforge.event.level.LevelEvent
|
||||
import net.neoforged.neoforge.event.server.ServerStoppingEvent
|
||||
import net.neoforged.neoforge.event.tick.LevelTickEvent
|
||||
import net.neoforged.neoforge.network.PacketDistributor
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kommons.io.DelegateSyncher
|
||||
import ru.dbotthepony.kommons.util.Listenable
|
||||
@ -45,21 +46,20 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
|
||||
import ru.dbotthepony.mc.otm.core.get
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.math.BlockRotation
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.core.math.minus
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.core.util.IntCounter
|
||||
import ru.dbotthepony.mc.otm.core.util.Savetables
|
||||
import ru.dbotthepony.mc.otm.core.util.TickList
|
||||
import ru.dbotthepony.mc.otm.core.util.countingLazy
|
||||
import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket
|
||||
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.once
|
||||
import ru.dbotthepony.mc.otm.onceServer
|
||||
import ru.dbotthepony.mc.otm.sometimeServer
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import java.util.function.BooleanSupplier
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Predicate
|
||||
import java.util.function.Supplier
|
||||
@ -74,7 +74,11 @@ import kotlin.reflect.KProperty
|
||||
abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_), INeighbourChangeListener {
|
||||
private var isSynchronizing = false
|
||||
|
||||
private val sidelessCaps = Reference2ObjectOpenHashMap<Capability<*>, SidelessCap<*>>()
|
||||
private val sidelessCaps = Reference2ObjectOpenHashMap<BlockCapability<*, *>, Any>()
|
||||
private val sidedCaps = Array(RelativeSide.entries.size) {
|
||||
Reference2ObjectOpenHashMap<BlockCapability<*, *>, Any>()
|
||||
}
|
||||
|
||||
protected val tickList = TickList()
|
||||
protected val blockStateChangesCounter = IntCounter()
|
||||
protected val dirtyListeners = Listenable.Impl<Unit>()
|
||||
@ -85,9 +89,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
val droppableContainers: Set<Container> = Collections.unmodifiableSet(_droppableContainers)
|
||||
val neighbourChangeListeners: Set<INeighbourChangeListener> = Collections.unmodifiableSet(_neighbourChangeListeners)
|
||||
|
||||
private val _sides = EnumMap<RelativeSide, Side>(RelativeSide::class.java)
|
||||
val sides: Map<RelativeSide, Side> = Collections.unmodifiableMap(_sides)
|
||||
|
||||
/**
|
||||
* Shared savetables, written both to level storage and to item tag
|
||||
*/
|
||||
@ -121,10 +122,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
open fun beforeDroppingItems(oldBlockState: BlockState, level: Level, blockPos: BlockPos, newBlockState: BlockState, movedByPiston: Boolean) {}
|
||||
open fun beforeDestroyedByPlayer(level: Level, blockPos: BlockPos, blockState: BlockState, player: Player) {}
|
||||
|
||||
fun side(side: RelativeSide) = sides[side]!!
|
||||
|
||||
private data class SidelessCap<T : Any>(val cap: T, var optional: LazyOptional<T>)
|
||||
|
||||
open fun tick() {
|
||||
tickList.tick()
|
||||
}
|
||||
@ -132,40 +129,45 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
/**
|
||||
* exposes capability when no side is specified
|
||||
*/
|
||||
protected fun <T : Any> exposeSideless(capability: Capability<T>, value: T) {
|
||||
protected fun <T : Any> exposeSideless(capability: BlockCapability<T, *>, value: T) {
|
||||
check(!sidelessCaps.containsKey(capability)) { "Already has globally exposed $capability!" }
|
||||
sidelessCaps[capability] = SidelessCap(value, LazyOptional.of { value })
|
||||
sidelessCaps[capability] = value
|
||||
setChanged()
|
||||
level?.invalidateCapabilities(blockPos)
|
||||
}
|
||||
|
||||
protected fun <T : Any> exposeSided(side: RelativeSide, capability: BlockCapability<T, *>, value: T) {
|
||||
val map = sidedCaps[side.ordinal]
|
||||
check(!map.containsKey(capability)) { "Already has exposed $capability on $side!" }
|
||||
map[capability] = value
|
||||
setChanged()
|
||||
level?.invalidateCapabilities(blockPos)
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes capability unconditionally, on all sides and sideless
|
||||
*/
|
||||
protected fun <T : Any> exposeGlobally(capability: Capability<T>, value: T, predicate: Predicate<RelativeSide> = Predicate { true }) {
|
||||
protected fun <T : Any> exposeGlobally(capability: BlockCapability<T, *>, value: T, predicate: Predicate<RelativeSide> = Predicate { true }) {
|
||||
exposeSideless(capability, value)
|
||||
|
||||
for (side in _sides.values)
|
||||
if (predicate.test(side.side))
|
||||
side.Cap(capability, value)
|
||||
}
|
||||
|
||||
protected fun exposeEnergyGlobally(value: IMatteryEnergyStorage, predicate: Predicate<RelativeSide> = Predicate { true }) {
|
||||
exposeGlobally(ForgeCapabilities.ENERGY, value, predicate)
|
||||
exposeGlobally(MatteryCapability.ENERGY, value, predicate)
|
||||
for (side in RelativeSide.entries)
|
||||
if (predicate.test(side))
|
||||
exposeSided(side, capability, value)
|
||||
}
|
||||
|
||||
protected fun exposeEnergySideless(value: IMatteryEnergyStorage) {
|
||||
exposeSideless(ForgeCapabilities.ENERGY, value)
|
||||
exposeSideless(MatteryCapability.ENERGY, value)
|
||||
exposeSideless(Capabilities.EnergyStorage.BLOCK, value)
|
||||
exposeSideless(MatteryCapability.BLOCK_ENERGY, value)
|
||||
}
|
||||
|
||||
protected fun exposeEnergy(side: RelativeSide, value: IMatteryEnergyStorage): ImmutableList<Side.Cap<*>> {
|
||||
return immutableList {
|
||||
val thisSide = _sides[side]!!
|
||||
|
||||
accept(thisSide.Cap(ForgeCapabilities.ENERGY, value))
|
||||
accept(thisSide.Cap(MatteryCapability.ENERGY, value))
|
||||
protected fun exposeEnergyGlobally(value: IMatteryEnergyStorage) {
|
||||
exposeGlobally(Capabilities.EnergyStorage.BLOCK, value)
|
||||
exposeGlobally(MatteryCapability.BLOCK_ENERGY, value)
|
||||
}
|
||||
|
||||
protected fun exposeEnergySided(side: RelativeSide, value: IMatteryEnergyStorage) {
|
||||
exposeSided(side, Capabilities.EnergyStorage.BLOCK, value)
|
||||
exposeSided(side, MatteryCapability.BLOCK_ENERGY, value)
|
||||
}
|
||||
|
||||
protected fun waitForServerLevel(lambda: () -> Unit) {
|
||||
@ -176,266 +178,38 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
}
|
||||
}
|
||||
|
||||
interface SideListener<T> : Supplier<LazyOptional<T>>, Listenable<LazyOptional<T>>
|
||||
|
||||
inner class Side(val side: RelativeSide) {
|
||||
init {
|
||||
check(!_sides.containsKey(side)) { "dafuq are you trying to do" }
|
||||
_sides[side] = this
|
||||
}
|
||||
|
||||
private val caps = Reference2ObjectOpenHashMap<Capability<*>, Cap<*>>()
|
||||
private val subscriptions = Reference2ObjectOpenHashMap<Capability<*>, SubRef<*>>()
|
||||
private val knownLOs = WeakHashSet<LazyOptional<*>>()
|
||||
|
||||
private inner class SubRef<T>(value: LazyOptional<T>) : SideListener<T> {
|
||||
var value: LazyOptional<T> = value
|
||||
set(value) {
|
||||
if (value !== field) {
|
||||
field = value
|
||||
listeners.accept(value)
|
||||
}
|
||||
}
|
||||
|
||||
private val listeners = Listenable.Impl<LazyOptional<T>>()
|
||||
|
||||
override fun addListener(listener: Consumer<LazyOptional<T>>): Listenable.L {
|
||||
val l = listeners.addListener(listener)
|
||||
if (level is ServerLevel) listener.accept(value)
|
||||
return l
|
||||
}
|
||||
|
||||
override fun get(): LazyOptional<T> {
|
||||
return value
|
||||
}
|
||||
|
||||
fun unset() {
|
||||
value = LazyOptional.empty()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> track(capability: Capability<T>): SideListener<T> {
|
||||
var subref = subscriptions[capability] as SideListener<T>?
|
||||
|
||||
if (subref == null) {
|
||||
subref = SubRef(LazyOptional.empty<Any?>()) as SubRef<T>
|
||||
subscriptions[capability] = subref
|
||||
level?.once { updateTracked(capability) }
|
||||
}
|
||||
|
||||
return subref
|
||||
}
|
||||
|
||||
fun trackEnergy(): SideListener<IEnergyStorage> {
|
||||
return track(ForgeCapabilities.ENERGY)
|
||||
}
|
||||
|
||||
fun updateTracked() {
|
||||
for (key in subscriptions.keys) {
|
||||
// Concurrent Modification safety:
|
||||
// we do not add nor remove keys from map, we only update values
|
||||
updateTracked(key)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTracked(capability: Capability<*>) {
|
||||
if (isRemoved || !SERVER_IS_LIVE) return
|
||||
val dir = blockRotation.side2Dir(side)
|
||||
val targetPos = blockPos + dir.normal
|
||||
|
||||
val chunk = level
|
||||
?.chunkSource
|
||||
?.getChunkNow(SectionPos.blockToSectionCoord(targetPos.x), SectionPos.blockToSectionCoord(targetPos.z))
|
||||
|
||||
val subref = subscriptions[capability] as SubRef<Any?>
|
||||
|
||||
if (chunk == null) {
|
||||
subref.unset()
|
||||
level?.once { updateTracked(capability) }
|
||||
return
|
||||
}
|
||||
|
||||
val entity = chunk.getBlockEntity(targetPos)
|
||||
|
||||
if (entity == null) {
|
||||
subref.unset()
|
||||
return
|
||||
}
|
||||
|
||||
val new = entity.getCapability(capability, dir.opposite)
|
||||
|
||||
if (!new.isPresent) {
|
||||
subref.unset()
|
||||
return
|
||||
}
|
||||
|
||||
if (subref.value !== new) {
|
||||
if (knownLOs.add(new)) {
|
||||
val ref = WeakReference(this)
|
||||
|
||||
new.addListener {
|
||||
ref.get()?.updateTracked(capability)
|
||||
}
|
||||
}
|
||||
|
||||
subref.value = new as LazyOptional<Any?>
|
||||
}
|
||||
}
|
||||
|
||||
operator fun <T : Any> get(capability: Capability<T>): Cap<T>? {
|
||||
return caps[capability] as Cap<T>?
|
||||
}
|
||||
|
||||
fun invalidate() {
|
||||
for (cap in caps.values)
|
||||
cap.invalidate()
|
||||
}
|
||||
|
||||
fun revive() {
|
||||
for (cap in caps.values)
|
||||
cap.revive()
|
||||
}
|
||||
|
||||
inner class Cap<T : Any>(val type: Capability<in T>, val capability: T) {
|
||||
init {
|
||||
check(!caps.containsKey(type)) { "Already has capability $type on side $side" }
|
||||
caps[type] = this
|
||||
}
|
||||
|
||||
var isExposed = true
|
||||
private set
|
||||
var isValid = true
|
||||
private set
|
||||
var isRemoved = false
|
||||
private set
|
||||
|
||||
var optional: LazyOptional<T> by object : ReadWriteProperty<Any?, LazyOptional<T>> {
|
||||
private var value: LazyOptional<T>? = null
|
||||
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): LazyOptional<T> {
|
||||
if (value == null) {
|
||||
value = LazyOptional.of { capability }
|
||||
}
|
||||
|
||||
return value!!
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: LazyOptional<T>) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
private set
|
||||
|
||||
fun remove() {
|
||||
if (!isRemoved) {
|
||||
isRemoved = true
|
||||
val removed = caps.remove(type)
|
||||
check(removed == this) { "$removed != $this" }
|
||||
optional.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
fun close() {
|
||||
if (!isRemoved && isExposed) {
|
||||
isExposed = false
|
||||
optional.invalidate()
|
||||
|
||||
if (SERVER_IS_LIVE)
|
||||
level?.once { if (!this@MatteryBlockEntity.isRemoved) setChanged() }
|
||||
}
|
||||
}
|
||||
|
||||
fun expose() {
|
||||
if (!isRemoved && !isExposed) {
|
||||
isExposed = true
|
||||
|
||||
if (isValid) {
|
||||
optional = LazyOptional.of { capability }
|
||||
|
||||
if (SERVER_IS_LIVE)
|
||||
level?.once { if (!this@MatteryBlockEntity.isRemoved) setChanged() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun invalidate() {
|
||||
if (!isRemoved && isValid) {
|
||||
isValid = false
|
||||
optional.invalidate()
|
||||
|
||||
if (SERVER_IS_LIVE)
|
||||
level?.once { if (!this@MatteryBlockEntity.isRemoved) setChanged() }
|
||||
}
|
||||
}
|
||||
|
||||
fun revive() {
|
||||
if (!isRemoved && !isValid) {
|
||||
isValid = true
|
||||
|
||||
if (isExposed) {
|
||||
optional = LazyOptional.of { capability }
|
||||
|
||||
if (SERVER_IS_LIVE)
|
||||
level?.once { if (!this@MatteryBlockEntity.isRemoved) setChanged() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val front = Side(RelativeSide.FRONT)
|
||||
val back = Side(RelativeSide.BACK)
|
||||
val left = Side(RelativeSide.LEFT)
|
||||
val right = Side(RelativeSide.RIGHT)
|
||||
val top = Side(RelativeSide.TOP)
|
||||
val bottom = Side(RelativeSide.BOTTOM)
|
||||
|
||||
override fun <T : Any> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
fun <T : Any> getCapability(cap: BlockCapability<T, *>, side: Direction?): T? {
|
||||
if (side != null) {
|
||||
return _sides[blockRotation.dir2Side(side)]!![cap]?.optional ?: super.getCapability(cap, side)
|
||||
return sidedCaps[blockRotation.dir2Side(side).ordinal][cap] as T?
|
||||
}
|
||||
|
||||
return sidelessCaps[cap]?.optional?.cast() ?: super.getCapability(cap, side)
|
||||
return sidelessCaps[cap] as T?
|
||||
}
|
||||
|
||||
override fun invalidateCaps() {
|
||||
super.invalidateCaps()
|
||||
|
||||
for (side in sides.values)
|
||||
side.invalidate()
|
||||
}
|
||||
|
||||
override fun reviveCaps() {
|
||||
super.reviveCaps()
|
||||
|
||||
for (side in sides.values)
|
||||
side.revive()
|
||||
}
|
||||
|
||||
final override fun saveAdditional(nbt: CompoundTag) {
|
||||
super.saveAdditional(nbt)
|
||||
saveShared(nbt)
|
||||
saveLevel(nbt)
|
||||
final override fun saveAdditional(nbt: CompoundTag, registry: Provider) {
|
||||
super.saveAdditional(nbt, registry)
|
||||
saveShared(nbt, registry)
|
||||
saveLevel(nbt, registry)
|
||||
}
|
||||
|
||||
/**
|
||||
* Saved both to item dropped, and to level storage
|
||||
*/
|
||||
open fun saveShared(nbt: CompoundTag) {
|
||||
savetables.serializeNBT(nbt)
|
||||
open fun saveShared(nbt: CompoundTag, registry: Provider) {
|
||||
savetables.serializeNBT(nbt, registry)
|
||||
}
|
||||
|
||||
/**
|
||||
* Only saved to level storage, discarded when dropped as item
|
||||
*/
|
||||
open fun saveLevel(nbt: CompoundTag) {
|
||||
savetablesLevel.serializeNBT(nbt)
|
||||
open fun saveLevel(nbt: CompoundTag, registry: Provider) {
|
||||
savetablesLevel.serializeNBT(nbt, registry)
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
savetables.deserializeNBT(nbt)
|
||||
savetablesLevel.deserializeNBT(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
savetables.deserializeNBT(registry, nbt)
|
||||
savetablesLevel.deserializeNBT(registry, nbt)
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION")
|
||||
@ -447,21 +221,13 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
val new = blockRotation
|
||||
|
||||
if (old != new) {
|
||||
for (side in _sides.values) {
|
||||
side.updateTracked()
|
||||
side.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
for (side in _sides.values) {
|
||||
side.revive()
|
||||
level?.invalidateCapabilities(blockPos)
|
||||
capabilityCaches.forEach { it.rebuildCache() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun neighborChanged(state: BlockState, level: Level, pos: BlockPos, neighbour: Block, neighbourPos: BlockPos, movedByPiston: Boolean) {
|
||||
_neighbourChangeListeners.forEach { it.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) }
|
||||
val dir = vec2Dir[vecKey(neighbourPos - blockPos)] ?: return
|
||||
_sides[blockRotation.dir2Side(dir)]!!.updateTracked()
|
||||
}
|
||||
|
||||
override fun setChanged() {
|
||||
@ -483,6 +249,51 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
dirtyListeners.accept(Unit)
|
||||
}
|
||||
|
||||
private val capabilityCaches = ArrayList<CapabilityCache<*>>()
|
||||
|
||||
inner class CapabilityCache<T : Any>(val side: RelativeSide, val capability: BlockCapability<T, in Direction?>) : Supplier<T?>, Listenable<T?> {
|
||||
private var currentVersion = 0
|
||||
private var cache: BlockCapabilityCache<T, in Direction?>? = null
|
||||
private val listeners = Listenable.Impl<T?>()
|
||||
|
||||
override fun addListener(listener: Consumer<T?>): Listenable.L {
|
||||
return listeners.addListener(listener)
|
||||
}
|
||||
|
||||
init {
|
||||
capabilityCaches.add(this)
|
||||
}
|
||||
|
||||
override fun get(): T? {
|
||||
return cache?.capability
|
||||
}
|
||||
|
||||
val isPresent: Boolean
|
||||
get() = cache?.capability != null
|
||||
|
||||
val isEmpty: Boolean
|
||||
get() = cache?.capability == null
|
||||
|
||||
fun rebuildCache() {
|
||||
val level = level as? ServerLevel
|
||||
|
||||
if (level == null) {
|
||||
cache = null
|
||||
return
|
||||
}
|
||||
|
||||
val creationVersion = ++currentVersion
|
||||
|
||||
cache = BlockCapabilityCache.create(
|
||||
capability, level, blockPos,
|
||||
blockRotation.side2Dir(side),
|
||||
{ !isRemoved || creationVersion != currentVersion },
|
||||
// IllegalStateException("Do not call getCapability on an invalid cache or from the invalidation listener!")
|
||||
// what a shame.
|
||||
{ onceServer { if (!isRemoved && creationVersion == currentVersion) listeners.accept(cache?.capability) } })
|
||||
}
|
||||
}
|
||||
|
||||
val syncher = DelegateSyncher()
|
||||
private val synchers = Object2ObjectArrayMap<ServerPlayer, DelegateSyncher.Remote>()
|
||||
|
||||
@ -494,30 +305,11 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
|
||||
if (!level.isClientSide) {
|
||||
subscribe()
|
||||
|
||||
if (old != null) {
|
||||
for (side in _sides.values) {
|
||||
side.updateTracked()
|
||||
side.invalidate()
|
||||
}
|
||||
|
||||
for (side in _sides.values) {
|
||||
side.revive()
|
||||
}
|
||||
} else {
|
||||
level.once {
|
||||
if (!isRemoved) {
|
||||
for (side in _sides.values) {
|
||||
side.updateTracked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
waitForServerLevel.forEach { it.invoke() }
|
||||
capabilityCaches.forEach { it.rebuildCache() }
|
||||
waitForServerLevel.clear()
|
||||
} else {
|
||||
waitForServerLevel.clear()
|
||||
|
||||
BlockEntitySyncPacket.applyBacklog(this)
|
||||
}
|
||||
}
|
||||
@ -718,7 +510,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
/**
|
||||
* Returns stream of players watching (tracking) specified [chunk]
|
||||
*/
|
||||
fun watchingPlayers(chunk: LevelChunk) = watchingPlayers(chunk.pos, chunk.level)
|
||||
fun watchingPlayers(chunk: LevelChunk) = watchingPlayers(chunk.pos, chunk.level!!)
|
||||
|
||||
private fun vecKey(value: Vec3i): Int {
|
||||
if (value.x !in -1 .. 1) return -1
|
||||
@ -759,7 +551,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
val payload = data.write()
|
||||
|
||||
if (payload != null) {
|
||||
GenericNetworkChannel.send(player, BlockEntitySyncPacket(be.blockPos, payload.array, payload.length))
|
||||
PacketDistributor.sendToPlayer(player, BlockEntitySyncPacket(be.blockPos, payload.array, payload.length))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity
|
||||
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import com.google.gson.JsonParser
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
@ -12,10 +15,12 @@ import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.capabilities.ICapabilityProvider
|
||||
import net.neoforged.neoforge.fluids.FluidStack
|
||||
import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
||||
import net.neoforged.neoforge.items.IItemHandler
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.capability.item.CombinedItemHandler
|
||||
@ -28,7 +33,6 @@ import ru.dbotthepony.mc.otm.capability.moveEnergy
|
||||
import ru.dbotthepony.mc.otm.capability.moveFluid
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.getValue
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.immutableMap
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
@ -67,16 +71,16 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
|
||||
protected open fun redstoneStatusUpdated(newBlocked: Boolean, oldBlocked: Boolean) {}
|
||||
|
||||
override fun saveShared(nbt: CompoundTag) {
|
||||
super.saveShared(nbt)
|
||||
override fun saveShared(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveShared(nbt, registry)
|
||||
|
||||
if (customDisplayName != null)
|
||||
nbt.putJson("Name", Component.Serializer.toJsonTree(customDisplayName!!))
|
||||
nbt.putJson("Name", JsonParser.parseString(Component.Serializer.toJson(customDisplayName!!, registry)))
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
customDisplayName = nbt.getJson("Name")?.let(Component.Serializer::fromJson)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
customDisplayName = nbt.getJson("Name")?.let { Component.Serializer.fromJson(it, registry) }
|
||||
}
|
||||
|
||||
override fun setLevel(level: Level) {
|
||||
@ -102,7 +106,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
val bottomDefault: FlowDirection = possibleModes,
|
||||
) {
|
||||
init {
|
||||
exposeSideless(ForgeCapabilities.FLUID_HANDLER, capability)
|
||||
exposeSideless(Capabilities.FluidHandler.BLOCK, capability)
|
||||
}
|
||||
|
||||
val front = Piece(RelativeSide.FRONT).also { it.flow = frontDefault }
|
||||
@ -132,11 +136,18 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
|
||||
inner class Piece(val side: RelativeSide) : IFluidHandler, ITickable {
|
||||
private val ticker = tickList.Ticker(this)
|
||||
private val controller = side(side).Cap(ForgeCapabilities.FLUID_HANDLER, this)
|
||||
private val neighbour = side(side).track(ForgeCapabilities.FLUID_HANDLER)
|
||||
private val neighbour = CapabilityCache(side, Capabilities.FluidHandler.BLOCK)
|
||||
|
||||
init {
|
||||
exposeSided(side, Capabilities.FluidHandler.BLOCK, this)
|
||||
}
|
||||
|
||||
private fun updateTickerState() {
|
||||
ticker.isEnabled = (automatePull || automatePush) && flow != FlowDirection.NONE && !redstoneControl.isBlockedByRedstone && neighbour.get().isPresent
|
||||
ticker.isEnabled =
|
||||
(automatePull || automatePush) &&
|
||||
flow != FlowDirection.NONE &&
|
||||
!redstoneControl.isBlockedByRedstone &&
|
||||
neighbour.isPresent
|
||||
}
|
||||
|
||||
init {
|
||||
@ -152,15 +163,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
if (access.get() != value) {
|
||||
access.accept(value)
|
||||
markDirtyFast()
|
||||
|
||||
if (value == FlowDirection.NONE) {
|
||||
controller.close()
|
||||
} else {
|
||||
controller.close()
|
||||
controller.expose()
|
||||
}
|
||||
|
||||
updateTickerState()
|
||||
level?.invalidateCapabilities(blockPos)
|
||||
}
|
||||
})
|
||||
|
||||
@ -193,7 +197,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
if (flow == FlowDirection.NONE || !automatePull && !automatePush || redstoneControl.isBlockedByRedstone)
|
||||
return
|
||||
|
||||
neighbour.get().ifPresentK {
|
||||
val it = neighbour.get() ?: return
|
||||
|
||||
if (flow.input && automatePull) {
|
||||
moveFluid(source = it, destination = capability)
|
||||
}
|
||||
@ -202,7 +207,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
moveFluid(source = capability, destination = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTanks(): Int {
|
||||
if (flow == FlowDirection.NONE) {
|
||||
@ -334,15 +338,12 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
put(RelativeSide.BOTTOM, bottomDefault)
|
||||
}
|
||||
|
||||
fun invalidate(force: Boolean = false) {
|
||||
for (piece in pieces.values) {
|
||||
piece.invalidate(force)
|
||||
}
|
||||
}
|
||||
|
||||
inner class Piece(val side: RelativeSide, val possibleModes: FlowDirection) : IMatteryEnergyStorage, ITickable {
|
||||
private val capControllers = exposeEnergy(side, this@Piece)
|
||||
private val neighbour = side(side).trackEnergy()
|
||||
private val neighbour = CapabilityCache(side, Capabilities.EnergyStorage.BLOCK)
|
||||
|
||||
init {
|
||||
exposeEnergySided(side, this)
|
||||
}
|
||||
|
||||
override var batteryLevel: Decimal by energy::batteryLevel
|
||||
override val maxBatteryLevel: Decimal by energy::maxBatteryLevel
|
||||
@ -356,7 +357,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
ticker.isEnabled = (automatePull || automatePush) &&
|
||||
energyFlow != FlowDirection.NONE &&
|
||||
!redstoneControl.isBlockedByRedstone &&
|
||||
neighbour.get().isPresent &&
|
||||
neighbour.isPresent &&
|
||||
(volatileEnergyValues || energy.batteryLevel.isPositive)
|
||||
}
|
||||
|
||||
@ -424,7 +425,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
neighbour.get().ifPresentK {
|
||||
val it = neighbour.get() ?: return
|
||||
|
||||
if (energyFlow.input && automatePull) {
|
||||
moveEnergy(source = it, destination = energy, simulate = false)
|
||||
}
|
||||
@ -433,7 +435,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
moveEnergy(source = energy, destination = it, simulate = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var energyFlow by syncher.enum(possibleModes, setter = { access, value ->
|
||||
require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" }
|
||||
@ -441,42 +442,10 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
if (access.get() != value) {
|
||||
access.accept(value)
|
||||
markDirtyFast()
|
||||
|
||||
if (value == FlowDirection.NONE) {
|
||||
for (controller in capControllers)
|
||||
controller.close()
|
||||
} else {
|
||||
for (controller in capControllers) {
|
||||
controller.close()
|
||||
controller.expose()
|
||||
}
|
||||
}
|
||||
|
||||
updateTickerState()
|
||||
level?.invalidateCapabilities(blockPos)
|
||||
}
|
||||
}).delegate
|
||||
|
||||
fun invalidate(force: Boolean = false) {
|
||||
if (force) {
|
||||
for (controller in capControllers) {
|
||||
controller.close()
|
||||
controller.expose()
|
||||
}
|
||||
|
||||
if (energyFlow == FlowDirection.NONE) {
|
||||
for (controller in capControllers) {
|
||||
controller.close()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (energyFlow != FlowDirection.NONE) {
|
||||
for (controller in capControllers) {
|
||||
controller.close()
|
||||
controller.expose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -550,7 +519,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
if (battery != null) caps.add(battery)
|
||||
|
||||
sideless = UnmodifiableItemHandler(CombinedItemHandler(caps))
|
||||
exposeSideless(ForgeCapabilities.ITEM_HANDLER, sideless)
|
||||
exposeSideless(Capabilities.ItemHandler.BLOCK, sideless)
|
||||
}
|
||||
|
||||
val front = Piece(RelativeSide.FRONT).also { it.mode = frontDefault }
|
||||
@ -585,10 +554,13 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
updateTickerState()
|
||||
}
|
||||
|
||||
private val capController = side(side).Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
||||
private val neighbour = side(side).track(ForgeCapabilities.ITEM_HANDLER)
|
||||
private val neighbour = CapabilityCache(side, Capabilities.ItemHandler.BLOCK)
|
||||
private val ticker = tickList.Ticker(this)
|
||||
|
||||
init {
|
||||
exposeSided(side, Capabilities.ItemHandler.BLOCK, this)
|
||||
}
|
||||
|
||||
private var innerSlotPull = 0
|
||||
private var outerSlotPull = 0
|
||||
|
||||
@ -596,11 +568,12 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
private var outerSlotPush = 0
|
||||
|
||||
private fun updateTickerState() {
|
||||
ticker.isEnabled = (automatePull || automatePush) && mode != ItemHandlerMode.DISABLED && !redstoneControl.isBlockedByRedstone && currentHandler.slots != 0 && neighbour.get().isPresent
|
||||
}
|
||||
|
||||
init {
|
||||
capController.close()
|
||||
ticker.isEnabled =
|
||||
(automatePull || automatePush) &&
|
||||
mode != ItemHandlerMode.DISABLED &&
|
||||
!redstoneControl.isBlockedByRedstone &&
|
||||
currentHandler.slots != 0 &&
|
||||
neighbour.isPresent
|
||||
}
|
||||
|
||||
var mode by syncher.enum(ItemHandlerMode.DISABLED, setter = { access, value ->
|
||||
@ -610,13 +583,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
access.accept(value)
|
||||
markDirtyFast()
|
||||
|
||||
if (value == ItemHandlerMode.DISABLED) {
|
||||
capController.close()
|
||||
} else {
|
||||
capController.close()
|
||||
capController.expose()
|
||||
}
|
||||
|
||||
currentHandler = when (value) {
|
||||
ItemHandlerMode.DISABLED -> EmptyItemHandler
|
||||
ItemHandlerMode.INPUT -> input!!
|
||||
@ -624,6 +590,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
ItemHandlerMode.INPUT_OUTPUT -> inputOutput!!
|
||||
ItemHandlerMode.BATTERY -> battery!!
|
||||
}
|
||||
|
||||
level?.invalidateCapabilities(blockPos)
|
||||
}
|
||||
}).delegate
|
||||
|
||||
@ -674,7 +642,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
if (mode == ItemHandlerMode.DISABLED || !automatePull && !automatePush || redstoneControl.isBlockedByRedstone || currentHandler.slots == 0)
|
||||
return
|
||||
|
||||
neighbour.get().ifPresentK {
|
||||
val it = neighbour.get() ?: return
|
||||
|
||||
if (it.slots == 0)
|
||||
return
|
||||
|
||||
@ -702,7 +671,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
||||
this.outerSlotPush = outerSlotPush
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSlots(): Int {
|
||||
return currentHandler.slots
|
||||
|
@ -3,12 +3,11 @@ package ru.dbotthepony.mc.otm.block.entity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import ru.dbotthepony.mc.otm.capability.energy
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.extractEnergy
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
|
||||
abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) {
|
||||
@ -31,7 +30,7 @@ abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229
|
||||
if (demand.isZero) return
|
||||
|
||||
for (stack in batteryContainer) {
|
||||
stack.getCapability(ForgeCapabilities.ENERGY).ifPresentK {
|
||||
stack.energy?.let {
|
||||
val diff = it.extractEnergy(demand, false)
|
||||
energy.receiveEnergy(diff, false)
|
||||
demand -= diff
|
||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.block.entity
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.chat.Component
|
||||
@ -75,26 +76,26 @@ abstract class MatteryWorkerBlockEntity<JobType : IJob>(
|
||||
|
||||
protected open fun onJobTick(status: JobStatus<JobType>, id: Int) {}
|
||||
|
||||
override fun saveShared(nbt: CompoundTag) {
|
||||
super.saveShared(nbt)
|
||||
override fun saveShared(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveShared(nbt, registry)
|
||||
nbt["jobs"] = ListTag().also {
|
||||
for ((i, job) in jobEventLoops.withIndex()) {
|
||||
it.add(job.serializeNBT().also {
|
||||
it.add(job.serializeNBT(registry).also {
|
||||
it["_id"] = i
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
|
||||
for (v in nbt.getCompoundList("jobs")) {
|
||||
if ("_id" in v) {
|
||||
val id = v.getInt("_id")
|
||||
|
||||
if (id in jobEventLoops.indices) {
|
||||
jobEventLoops[id].deserializeNBT(v)
|
||||
jobEventLoops[id].deserializeNBT(registry, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity
|
||||
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable
|
||||
import ru.dbotthepony.kommons.io.DelegateSyncher
|
||||
import ru.dbotthepony.kommons.util.Listenable
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
@ -25,14 +26,14 @@ abstract class AbstractRedstoneControl : INBTSerializable<CompoundTag?>, Listena
|
||||
return listeners.addListener(listener)
|
||||
}
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it[SETTING_KEY] = redstoneSetting.toString()
|
||||
it[SIGNAL_KEY] = redstoneSignal
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag?) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag?) {
|
||||
if (nbt == null) {
|
||||
redstoneSetting = RedstoneSetting.LOW
|
||||
redstoneSignal = 0
|
||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.block.entity.blackhole
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@ -18,13 +19,12 @@ import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.common.Tags
|
||||
import net.neoforged.neoforge.common.Tags
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.block.BlackHoleBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue.Companion.queueForLevel
|
||||
import ru.dbotthepony.mc.otm.config.ServerConfig
|
||||
import ru.dbotthepony.mc.otm.core.damageType
|
||||
import ru.dbotthepony.mc.otm.core.getExplosionResistance
|
||||
@ -101,37 +101,6 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
val level = level as? ServerLevel ?: return
|
||||
|
||||
level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL)
|
||||
|
||||
if (gravitationStrength > 0.25) {
|
||||
val x0 = blockPos.x + 0.5
|
||||
val y0 = blockPos.y + 0.5
|
||||
val z0 = blockPos.z + 0.5
|
||||
val queue = queueForLevel(level)
|
||||
var radius = 0
|
||||
|
||||
while (radius < Math.ceil(gravitationStrength * 4)) {
|
||||
queue.explodeRing(
|
||||
x0,
|
||||
y0,
|
||||
z0,
|
||||
radius.toDouble(), Math.min(20.0, Math.max(1.0, (gravitationStrength * 4 - radius) * 20)).toFloat()
|
||||
)
|
||||
|
||||
radius++
|
||||
}
|
||||
} else {
|
||||
level.explode(
|
||||
null,
|
||||
MatteryDamageSource(level.registryAccess().damageType(MDamageTypes.HAWKING_RADIATION)),
|
||||
null,
|
||||
blockPos.x + 0.5,
|
||||
blockPos.y + 0.5,
|
||||
blockPos.z + 0.5,
|
||||
gravitationStrength.toFloat() * 60,
|
||||
false,
|
||||
Level.ExplosionInteraction.BLOCK // TODO: 1.19.3
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateGravStrength() {
|
||||
@ -162,19 +131,14 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
affectedBoundsAABB = AABB.of(affectedBounds)
|
||||
}
|
||||
|
||||
override fun getRenderBoundingBox(): AABB {
|
||||
return AABB(blockPos.offset(-GravitationStabilizerBlockEntity.RANGE, -GravitationStabilizerBlockEntity.RANGE, -GravitationStabilizerBlockEntity.RANGE), blockPos.offset(
|
||||
GravitationStabilizerBlockEntity.RANGE, GravitationStabilizerBlockEntity.RANGE, GravitationStabilizerBlockEntity.RANGE))
|
||||
}
|
||||
|
||||
override fun saveLevel(nbt: CompoundTag) {
|
||||
super.saveLevel(nbt)
|
||||
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveLevel(nbt, registry)
|
||||
nbt["mass"] = mass.serializeNBT()
|
||||
nbt["spin_direction"] = spinDirection
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
mass = nbt.map("mass", Decimal::deserializeNBT) ?: BASELINE_MASS
|
||||
spinDirection = nbt.getBoolean("spin_direction")
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.blackhole
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.core.math.times
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
|
||||
class BlockEntityExplosionDebugger(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(MBlockEntities.DEBUG_EXPLOSION_SMALL, p_155229_, p_155230_) {
|
||||
private var hive: ExplosionRayHive? = null
|
||||
|
||||
fun tick() {
|
||||
if (hive == null) {
|
||||
val hive = ExplosionRayHive(level as ServerLevel)
|
||||
this.hive = hive
|
||||
|
||||
val tx = blockPos.x.toDouble() + 0.5
|
||||
val ty = blockPos.y.toDouble() + 0.5
|
||||
val tz = blockPos.z.toDouble() + 0.5
|
||||
val tpos = Vec3(tx, ty, tz)
|
||||
|
||||
for (normal in ExplosionRayHive.evenlyDistributedPoints(1000)) {
|
||||
hive.addRay(normal + tpos, normal, 200.0)
|
||||
}
|
||||
}
|
||||
|
||||
hive!!.step()
|
||||
}
|
||||
}
|
||||
|
||||
class BlockEntitySphereDebugger(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(MBlockEntities.DEBUG_SPHERE_POINTS, p_155229_, p_155230_) {
|
||||
private var placed = false
|
||||
|
||||
fun tick() {
|
||||
if (!placed) {
|
||||
placed = true
|
||||
|
||||
for (normal in ExplosionRayHive.evenlyDistributedPoints(400)) {
|
||||
val multiplied = normal * 20.0
|
||||
level!!.setBlock(blockPos + BlockPos(multiplied.x.toInt(), multiplied.y.toInt(), multiplied.z.toInt()), Blocks.COAL_BLOCK.defaultBlockState(), Block.UPDATE_ALL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,687 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.blackhole
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.DoubleTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.util.datafix.DataFixTypes
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Explosion
|
||||
import net.minecraft.world.level.ExplosionDamageCalculator
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
import net.minecraft.world.level.saveddata.SavedData
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.event.TickEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.block.BlockExplosionDebugger
|
||||
import ru.dbotthepony.mc.otm.core.*
|
||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||
import ru.dbotthepony.mc.otm.core.math.component1
|
||||
import ru.dbotthepony.mc.otm.core.math.component2
|
||||
import ru.dbotthepony.mc.otm.core.math.component3
|
||||
import ru.dbotthepony.mc.otm.core.math.left
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.core.math.rotateAroundAxis
|
||||
import ru.dbotthepony.mc.otm.core.math.up
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.registry.MDamageTypes
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.registry.MatteryDamageSource
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.math.acos
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
private fun round(v: Double): Int {
|
||||
return (v + 0.5).toInt()
|
||||
}
|
||||
|
||||
private val sphere = arrayOf(
|
||||
// ядро
|
||||
BlockPos(-1, -1, -1),
|
||||
BlockPos(-1, -1, 0),
|
||||
BlockPos(-1, -1, 1),
|
||||
BlockPos(-1, 0, -1),
|
||||
BlockPos(-1, 0, 0),
|
||||
BlockPos(-1, 0, 1),
|
||||
BlockPos(-1, 1, -1),
|
||||
BlockPos(-1, 1, 0),
|
||||
BlockPos(-1, 1, 1),
|
||||
BlockPos(0, -1, -1),
|
||||
BlockPos(0, -1, 0),
|
||||
BlockPos(0, -1, 1),
|
||||
BlockPos(0, 0, -1),
|
||||
BlockPos(0, 0, 0),
|
||||
BlockPos(0, 0, 1),
|
||||
BlockPos(0, 1, -1),
|
||||
BlockPos(0, 1, 0),
|
||||
BlockPos(0, 1, 1),
|
||||
BlockPos(1, -1, -1),
|
||||
BlockPos(1, -1, 0),
|
||||
BlockPos(1, -1, 1),
|
||||
BlockPos(1, 0, -1),
|
||||
BlockPos(1, 0, 0),
|
||||
BlockPos(1, 0, 1),
|
||||
BlockPos(1, 1, -1),
|
||||
BlockPos(1, 1, 0),
|
||||
BlockPos(1, 1, 1),
|
||||
|
||||
// столбы
|
||||
BlockPos(-2, 0, 0),
|
||||
BlockPos(2, 0, 0),
|
||||
BlockPos(0, 2, 0),
|
||||
BlockPos(0, -2, 0),
|
||||
BlockPos(0, 0, 2),
|
||||
BlockPos(0, 0, -2),
|
||||
)
|
||||
|
||||
private val initialDirections = arrayOf(
|
||||
Vector(1.0, 0.0, 0.0),
|
||||
Vector(-1.0, 0.0, 0.0),
|
||||
Vector(0.0, 1.0, 0.0),
|
||||
Vector(0.0, -1.0, 0.0),
|
||||
Vector(0.0, 0.0, 1.0),
|
||||
Vector(0.0, 0.0, -1.0),
|
||||
|
||||
Vector(-1.0, -1.0, -1.0).normalize(),
|
||||
Vector(1.0, -1.0, 1.0).normalize(),
|
||||
Vector(1.0, -1.0, -1.0).normalize(),
|
||||
Vector(-1.0, -1.0, 1.0).normalize(),
|
||||
Vector(-1.0, 1.0, -1.0).normalize(),
|
||||
Vector(1.0, 1.0, 1.0).normalize(),
|
||||
Vector(1.0, 1.0, -1.0).normalize(),
|
||||
Vector(-1.0, 1.0, 1.0).normalize(),
|
||||
)
|
||||
|
||||
class ExplosionSphere(val hive: ExplosionSphereHive, var pos: Vec3, var stepVelocity: Vec3, var force: Double) {
|
||||
val initialPos = pos
|
||||
private var lastSplitPos = pos
|
||||
val level: ServerLevel get() = hive.level
|
||||
val blockPos: BlockPos get() = BlockPos(round(pos.x), round(pos.y), round(pos.z))
|
||||
|
||||
fun travelled(): Double {
|
||||
return pos.distanceTo(initialPos)
|
||||
}
|
||||
|
||||
private fun travelledFromLastSplit(): Double {
|
||||
return pos.distanceTo(lastSplitPos)
|
||||
}
|
||||
|
||||
fun step(): Boolean {
|
||||
if (force <= 0.0) {
|
||||
return false
|
||||
}
|
||||
|
||||
val blockPos = blockPos
|
||||
|
||||
for (point in sphere) {
|
||||
val finalPos = blockPos + point
|
||||
val block = level.getBlockState(finalPos)
|
||||
|
||||
if (!block.isAir && block.block !is BlockExplosionDebugger) {
|
||||
val explosion = Explosion(level, null, null, null, pos.x, pos.y, pos.z, force.toFloat(), false, Explosion.BlockInteraction.DESTROY_WITH_DECAY)
|
||||
val explosionResistance = block.getExplosionResistance(level, blockPos, explosion)
|
||||
|
||||
if (explosionResistance > force) {
|
||||
// поглощено
|
||||
// TODO: вместо полного поглощения отражение
|
||||
force = 0.0
|
||||
return false
|
||||
} else {
|
||||
// взорвано
|
||||
force -= explosionResistance
|
||||
|
||||
// TODO: дропы когда будет добавлена более общая версия
|
||||
level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos += stepVelocity
|
||||
|
||||
force -= 0.4
|
||||
|
||||
if (travelledFromLastSplit() >= TRAVEL_TO_SPLIT && force >= 10) {
|
||||
force /= 2.0
|
||||
|
||||
val up = stepVelocity.up()
|
||||
val left = stepVelocity.left()
|
||||
|
||||
val a = stepVelocity.rotateAroundAxis(up, Math.PI / 4)
|
||||
val b = stepVelocity.rotateAroundAxis(up, -Math.PI / 4)
|
||||
val c = stepVelocity.rotateAroundAxis(left, Math.PI / 4)
|
||||
val d = stepVelocity.rotateAroundAxis(left, -Math.PI / 4)
|
||||
|
||||
hive.addRay(pos, a, force)
|
||||
hive.addRay(pos, b, force)
|
||||
hive.addRay(pos, c, force)
|
||||
hive.addRay(pos, d, force)
|
||||
|
||||
lastSplitPos = pos
|
||||
}
|
||||
|
||||
return force > 0.0
|
||||
}
|
||||
|
||||
fun serializeNbt(): CompoundTag {
|
||||
return CompoundTag()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TRAVEL_TO_SPLIT = 4.0
|
||||
|
||||
fun deserializeNbt(hive: ExplosionSphereHive, tag: CompoundTag): ExplosionSphere {
|
||||
return ExplosionSphere(hive, Vector.ZERO, Vector.ZERO, 0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosionSphereHive(val level: ServerLevel) {
|
||||
private val spheres = ArrayList<ExplosionSphere>()
|
||||
|
||||
var stepNumber = 0
|
||||
private set
|
||||
|
||||
fun addRay(pos: Vec3, stepVelocity: Vec3, force: Double) {
|
||||
spheres.add(ExplosionSphere(this, pos, stepVelocity, force))
|
||||
}
|
||||
|
||||
fun addDefaultRays(pos: Vec3, force: Double) {
|
||||
for (stepVelocity in initialDirections) {
|
||||
addRay(pos, stepVelocity, force * 8)
|
||||
}
|
||||
}
|
||||
|
||||
fun step() {
|
||||
stepNumber++
|
||||
|
||||
val toRemove = ArrayList<Int>()
|
||||
|
||||
for (i in 0 until spheres.size) {
|
||||
if (!spheres[i].step()) {
|
||||
toRemove.add(i)
|
||||
}
|
||||
}
|
||||
|
||||
for (i in toRemove.size - 1 downTo 0) {
|
||||
spheres.removeAt(toRemove[i])
|
||||
}
|
||||
}
|
||||
|
||||
fun serializeNbt(): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["spheres"] = ListTag().also {
|
||||
for (ray in spheres)
|
||||
it.add(ray.serializeNbt())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deserializeNbt(tag: CompoundTag) {
|
||||
(tag["spheres"] as? ListTag)?.also {
|
||||
for (elem in it) {
|
||||
spheres.add(ExplosionSphere.deserializeNbt(this, elem as CompoundTag))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isEmpty(): Boolean {
|
||||
return spheres.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosionRay(val hive: ExplosionRayHive, var pos: Vec3, var stepVelocity: Vec3, var force: Double) {
|
||||
val initialPos = pos
|
||||
private var lastSplitPos = pos
|
||||
val level: ServerLevel get() = hive.level
|
||||
val blockPos: BlockPos get() = BlockPos(round(pos.x), round(pos.y), round(pos.z))
|
||||
private var prev: MutableInt? = null
|
||||
|
||||
fun travelled(): Double {
|
||||
return pos.distanceTo(initialPos)
|
||||
}
|
||||
|
||||
private fun travelledFromLastSplit(): Double {
|
||||
return pos.distanceTo(lastSplitPos)
|
||||
}
|
||||
|
||||
fun step(spread: Boolean): Boolean {
|
||||
if (force <= 0.0) {
|
||||
return false
|
||||
}
|
||||
|
||||
val blockPos = blockPos
|
||||
|
||||
if (!level.isInWorldBounds(blockPos))
|
||||
return false
|
||||
|
||||
// val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(blockPos.x), SectionPos.blockToSectionCoord(blockPos.z)) ?: return true
|
||||
val block = level.getBlockState(blockPos)
|
||||
|
||||
if (!block.isAir && block.block !is BlockExplosionDebugger) {
|
||||
val explosion = Explosion(level, null, null, null, pos.x, pos.y, pos.z, force.toFloat(), false, Explosion.BlockInteraction.DESTROY_WITH_DECAY)
|
||||
val explosionResistance = block.getExplosionResistance(level, blockPos, explosion)
|
||||
|
||||
if (explosionResistance > force) {
|
||||
// поглощено
|
||||
// TODO: вместо полного поглощения отражение
|
||||
force = 0.0
|
||||
return false
|
||||
} else {
|
||||
// взорвано
|
||||
force -= explosionResistance
|
||||
|
||||
// TODO: дропы когда будет добавлена более общая версия
|
||||
level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL)
|
||||
}
|
||||
}
|
||||
|
||||
val old = this.blockPos
|
||||
pos += stepVelocity
|
||||
val new = this.blockPos
|
||||
|
||||
if (old != new) {
|
||||
val prev = prev
|
||||
|
||||
if (prev != null) {
|
||||
prev.dec()
|
||||
|
||||
if (prev.value <= 0) {
|
||||
hive.checkKey(old)
|
||||
}
|
||||
}
|
||||
|
||||
this.prev = hive.incDensity(new)
|
||||
}
|
||||
|
||||
force -= 0.4
|
||||
|
||||
if (spread && travelledFromLastSplit() >= TRAVEL_TO_SPLIT * sqrt(travelled() / 9.0) && force >= 10) {
|
||||
force /= 2.0
|
||||
|
||||
val up = stepVelocity.up()
|
||||
val left = stepVelocity.left()
|
||||
|
||||
val a = stepVelocity.rotateAroundAxis(up, Math.PI / 5.5)
|
||||
val b = stepVelocity.rotateAroundAxis(up, -Math.PI / 5.5)
|
||||
val c = stepVelocity.rotateAroundAxis(left, Math.PI / 5.5)
|
||||
val d = stepVelocity.rotateAroundAxis(left, -Math.PI / 5.5)
|
||||
|
||||
hive.addRay(pos, a, force)
|
||||
hive.addRay(pos, b, force)
|
||||
hive.addRay(pos, c, force)
|
||||
hive.addRay(pos, d, force)
|
||||
|
||||
lastSplitPos = pos
|
||||
}
|
||||
|
||||
return force > 0f
|
||||
}
|
||||
|
||||
fun serializeNbt(): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["pos"] = ListTag().also {
|
||||
it.add(DoubleTag.valueOf(pos.x))
|
||||
it.add(DoubleTag.valueOf(pos.y))
|
||||
it.add(DoubleTag.valueOf(pos.z))
|
||||
}
|
||||
|
||||
it["stepVelocity"] = ListTag().also {
|
||||
it.add(DoubleTag.valueOf(stepVelocity.x))
|
||||
it.add(DoubleTag.valueOf(stepVelocity.y))
|
||||
it.add(DoubleTag.valueOf(stepVelocity.z))
|
||||
}
|
||||
|
||||
it["force"] = force
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TRAVEL_TO_SPLIT = 4.0
|
||||
|
||||
fun deserializeNbt(hive: ExplosionRayHive, tag: CompoundTag): ExplosionRay {
|
||||
val pos = tag["pos"] as ListTag
|
||||
val stepVelocity = tag["stepVelocity"] as ListTag
|
||||
|
||||
return ExplosionRay(hive,
|
||||
Vector((pos[0] as DoubleTag).asDouble, (pos[1] as DoubleTag).asDouble, (pos[2] as DoubleTag).asDouble),
|
||||
Vector((stepVelocity[0] as DoubleTag).asDouble, (stepVelocity[1] as DoubleTag).asDouble, (stepVelocity[2] as DoubleTag).asDouble),
|
||||
(tag["force"] as DoubleTag).asDouble
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MutableInt(var value: Int = 0) {
|
||||
fun inc() {value++}
|
||||
fun dec() {value--}
|
||||
fun zero() = value <= 0
|
||||
}
|
||||
|
||||
class ExplosionRayHive(val level: ServerLevel) {
|
||||
private val rays = ArrayList<ExplosionRay>()
|
||||
private val densityMap = HashMap<BlockPos, MutableInt>()
|
||||
var stepNumber = 0
|
||||
private set
|
||||
|
||||
fun incDensity(pos: BlockPos): MutableInt {
|
||||
return densityMap.computeIfAbsent(pos) {MutableInt()}.also(MutableInt::inc)
|
||||
}
|
||||
|
||||
fun decDensity(pos: BlockPos) {
|
||||
val value = densityMap.computeIfAbsent(pos) {MutableInt()}
|
||||
value.dec()
|
||||
|
||||
if (value.zero()) {
|
||||
densityMap.remove(pos)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkKey(pos: BlockPos) {
|
||||
val value = densityMap.computeIfAbsent(pos) {MutableInt()}
|
||||
|
||||
if (value.zero()) {
|
||||
densityMap.remove(pos)
|
||||
}
|
||||
}
|
||||
|
||||
fun addRay(pos: Vec3, stepVelocity: Vec3, force: Double) {
|
||||
rays.add(ExplosionRay(this, pos, stepVelocity, force))
|
||||
}
|
||||
|
||||
fun step() {
|
||||
stepNumber++
|
||||
|
||||
val toRemove = ArrayList<Int>()
|
||||
val density = calculateDensity()
|
||||
|
||||
for (i in 0 until rays.size) {
|
||||
if (!rays[i].step(density < 3.0)) {
|
||||
toRemove.add(i)
|
||||
decDensity(rays[i].blockPos)
|
||||
}
|
||||
}
|
||||
|
||||
for (i in toRemove.size - 1 downTo 0) {
|
||||
rays.removeAt(toRemove[i])
|
||||
}
|
||||
|
||||
if (stepNumber % 4 == 0) {
|
||||
LOGGER.info("At step {} density of hive {} with {} elements is {}", stepNumber, this, rays.size, density)
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateDensity(): Double {
|
||||
return rays.size.toDouble() / densityMap.size
|
||||
}
|
||||
|
||||
fun serializeNbt(): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["rays"] = ListTag().also {
|
||||
for (ray in rays)
|
||||
it.add(ray.serializeNbt())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deserializeNbt(tag: CompoundTag) {
|
||||
(tag["rays"] as? ListTag)?.also {
|
||||
for (elem in it) {
|
||||
rays.add(ExplosionRay.deserializeNbt(this, elem as CompoundTag))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isEmpty(): Boolean {
|
||||
return rays.isEmpty()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
private val SQUARE_5 = sqrt(5.0)
|
||||
|
||||
fun evenlyDistributedPoints(amount: Int): List<Vec3> {
|
||||
val list = ArrayList<Vec3>()
|
||||
|
||||
for (i in 0 .. amount) {
|
||||
val idx = i.toDouble() / amount
|
||||
val phi = acos(1.0 - 2.0 * idx)
|
||||
val theta = Math.PI * (1.0 + SQUARE_5) * i
|
||||
|
||||
list.add(Vec3(cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi)))
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object BlackHoleExplosionDamageCalculator : ExplosionDamageCalculator() {
|
||||
override fun getBlockExplosionResistance(
|
||||
explosion: Explosion,
|
||||
getter: BlockGetter,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
fstate: FluidState
|
||||
): Optional<Float> {
|
||||
return if (state.isAir && fstate.isEmpty) Optional.empty() else Optional.of(
|
||||
Math.sqrt(
|
||||
Math.max(
|
||||
0f,
|
||||
Math.max(
|
||||
state.getExplosionResistance(getter, pos, explosion),
|
||||
fstate.getExplosionResistance(getter, pos, explosion)
|
||||
)
|
||||
).toDouble()
|
||||
).toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private data class RingExplosion(val x: Double, val y: Double, val z: Double, val radius: Double, val strength: Float) {
|
||||
fun serializeNBT(): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["x"] = x
|
||||
it["y"] = y
|
||||
it["z"] = z
|
||||
it["radius"] = radius
|
||||
it["strength"] = strength
|
||||
}
|
||||
}
|
||||
|
||||
fun explode(queue: ExplosionQueue) {
|
||||
for (pos in ExplosionRayHive.evenlyDistributedPoints(radius.toInt() * 80)) {
|
||||
val (x, y, z) = pos
|
||||
|
||||
queue.explode(
|
||||
this.x + x * radius * 15,
|
||||
this.y + y * radius * 15,
|
||||
this.z + z * radius * 15,
|
||||
strength
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun deserializeNBT(tag: CompoundTag): RingExplosion {
|
||||
return RingExplosion(
|
||||
tag.getDouble("x"),
|
||||
tag.getDouble("y"),
|
||||
tag.getDouble("z"),
|
||||
tag.getDouble("radius"),
|
||||
tag.getFloat("strength")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class QueuedExplosion(val x: Double, val y: Double, val z: Double, val radius: Float) {
|
||||
fun serializeNBT(): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["x"] = x
|
||||
it["y"] = y
|
||||
it["z"] = z
|
||||
it["radius"] = radius
|
||||
}
|
||||
}
|
||||
|
||||
fun explode(level: Level) {
|
||||
level.explode(
|
||||
null,
|
||||
MatteryDamageSource(level.registryAccess().damageType(MDamageTypes.HAWKING_RADIATION)),
|
||||
BlackHoleExplosionDamageCalculator,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
radius,
|
||||
false,
|
||||
Level.ExplosionInteraction.BLOCK // TODO: 1.19.3
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun deserializeNBT(tag: CompoundTag): QueuedExplosion {
|
||||
return QueuedExplosion(tag.getDouble("x"), tag.getDouble("y"), tag.getDouble("z"), tag.getFloat("radius"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosionQueue(private val level: ServerLevel) : SavedData() {
|
||||
private var indexExplosion = 0
|
||||
private var indexRing = 0
|
||||
private val explosions = ArrayList<QueuedExplosion>()
|
||||
private val rings = ArrayList<RingExplosion>()
|
||||
private val hives = ArrayList<ExplosionRayHive>()
|
||||
|
||||
override fun save(tag: CompoundTag): CompoundTag {
|
||||
val listExplosions = ListTag()
|
||||
val listRings = ListTag()
|
||||
|
||||
for (i in indexExplosion until explosions.size)
|
||||
listExplosions.add(explosions[i].serializeNBT())
|
||||
|
||||
for (i in indexRing until rings.size)
|
||||
listRings.add(rings[i].serializeNBT())
|
||||
|
||||
tag["explosions"] = listExplosions
|
||||
tag["rings"] = listRings
|
||||
// tag["hives"] = ListTag().also {
|
||||
// for (hive in hives) {
|
||||
// it.add(hive.serializeNbt())
|
||||
// }
|
||||
// }
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
fun load(tag: CompoundTag) {
|
||||
explosions.clear()
|
||||
rings.clear()
|
||||
hives.clear()
|
||||
|
||||
indexExplosion = 0
|
||||
indexRing = 0
|
||||
|
||||
for (explosion in tag.getList("explosions", Tag.TAG_COMPOUND.toInt()))
|
||||
explosions.add(QueuedExplosion.deserializeNBT(explosion as CompoundTag))
|
||||
|
||||
for (ring in tag.getList("rings", Tag.TAG_COMPOUND.toInt()))
|
||||
rings.add(RingExplosion.deserializeNBT(ring as CompoundTag))
|
||||
|
||||
for (hive in tag.getList("hives", Tag.TAG_COMPOUND.toInt()))
|
||||
hives.add(ExplosionRayHive(level).also { it.deserializeNbt(hive as CompoundTag) })
|
||||
}
|
||||
|
||||
fun explode(x: Double, y: Double, z: Double, radius: Float) {
|
||||
if (level.isOutsideBuildHeight(BlockPos(x.toInt(), y.toInt() + 24, z.toInt())) || level.isOutsideBuildHeight(BlockPos(x.toInt(), y.toInt() - 24, z.toInt())))
|
||||
return
|
||||
|
||||
explosions.add(QueuedExplosion(x, y, z, radius))
|
||||
isDirty = true
|
||||
}
|
||||
|
||||
fun explodeRing(x: Double, y: Double, z: Double, radius: Double, strength: Float) {
|
||||
rings.add(RingExplosion(x, y, z, radius, strength))
|
||||
isDirty = true
|
||||
}
|
||||
|
||||
fun explodeRays(tpos: Vector, force: Double) {
|
||||
val hive = ExplosionRayHive(level)
|
||||
hives.add(hive)
|
||||
|
||||
for (normal in ExplosionRayHive.evenlyDistributedPoints(1000)) {
|
||||
hive.addRay(normal + tpos, normal, force)
|
||||
}
|
||||
|
||||
isDirty = true
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
if (explosions.size != 0) {
|
||||
isDirty = true
|
||||
var iterations = 0
|
||||
|
||||
for (i in indexExplosion until explosions.size) {
|
||||
explosions[i].explode(level)
|
||||
indexExplosion++
|
||||
|
||||
if (iterations++ == 4) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (indexExplosion >= explosions.size) {
|
||||
indexExplosion = 0
|
||||
explosions.clear()
|
||||
}
|
||||
} else if (rings.size != 0) {
|
||||
if (indexRing >= rings.size) {
|
||||
indexRing = 0
|
||||
rings.clear()
|
||||
} else {
|
||||
rings[indexRing++].explode(this)
|
||||
}
|
||||
}
|
||||
|
||||
for (i in hives.size - 1 downTo 0) {
|
||||
isDirty = true
|
||||
hives[i].step()
|
||||
|
||||
if (hives[i].isEmpty()) {
|
||||
hives.removeAt(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun queueForLevel(level: ServerLevel): ExplosionQueue {
|
||||
return level.dataStorage.computeIfAbsent(
|
||||
Factory({ ExplosionQueue(level) }, {
|
||||
val factory = ExplosionQueue(level)
|
||||
factory.load(it)
|
||||
factory
|
||||
}, DataFixTypes.LEVEL),
|
||||
"otm_blackhole_explosion_queue"
|
||||
)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onWorldTick(event: TickEvent.LevelTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.START && event.level is ServerLevel) {
|
||||
queueForLevel(event.level as ServerLevel).tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
|
||||
import ru.dbotthepony.mc.otm.block.CableBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
@ -43,23 +43,23 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
|
||||
init {
|
||||
check(side !in energySidesInternal)
|
||||
energySidesInternal[side] = this
|
||||
sides[side]!!.Cap(ForgeCapabilities.ENERGY, this)
|
||||
exposeSided(side, Capabilities.EnergyStorage.BLOCK, this)
|
||||
}
|
||||
|
||||
val neighbour = sides[side]!!.trackEnergy()
|
||||
val neighbour = CapabilityCache(side, Capabilities.EnergyStorage.BLOCK)
|
||||
|
||||
init {
|
||||
waitForServerLevel {
|
||||
neighbour.addListener(Consumer {
|
||||
if (isEnabled) {
|
||||
if (it.isPresent) {
|
||||
if (it.resolve().get() !is CableSide) {
|
||||
if (neighbour.isPresent) {
|
||||
if (neighbour.get() !is CableSide) {
|
||||
node.graph.livelyNodes.add(node)
|
||||
}
|
||||
}
|
||||
|
||||
onceServer {
|
||||
updateBlockState(blockRotation.side2Dir(side), it.isPresent || node.neighboursView[GraphNode.link(blockRotation.side2Dir(side))] != null)
|
||||
updateBlockState(blockRotation.side2Dir(side), neighbour.isPresent || node.neighboursView[GraphNode.link(blockRotation.side2Dir(side))] != null)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -144,8 +144,8 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
|
||||
}
|
||||
|
||||
init {
|
||||
sides.keys.forEach { CableSide(it) }
|
||||
exposeGlobally(MatteryCapability.ENERGY_CABLE_NODE, node)
|
||||
RelativeSide.entries.forEach { CableSide(it) }
|
||||
exposeSideless(MatteryCapability.ENERGY_CABLE_NODE, node)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,10 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.cable
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||
import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||
import ru.dbotthepony.mc.otm.capability.receiveEnergy
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.graph.GraphNodeList
|
||||
import java.util.PriorityQueue
|
||||
import java.util.*
|
||||
import kotlin.math.ln
|
||||
|
||||
class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableGraph>() {
|
||||
@ -102,7 +98,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
continue
|
||||
}
|
||||
|
||||
side.neighbour.get().ifPresentK {
|
||||
side.neighbour.get()?.let {
|
||||
if (it !is EnergyCableBlockEntity.CableSide) {
|
||||
val limit = getPath(fromNode, node)
|
||||
hit = true
|
||||
|
@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.block.entity.decorative
|
||||
|
||||
import net.minecraft.advancements.CriteriaTriggers
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.LongTag
|
||||
import net.minecraft.nbt.StringTag
|
||||
@ -23,7 +24,7 @@ import net.minecraft.world.level.storage.loot.LootParams
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
@ -84,18 +85,18 @@ class CargoCrateBlockEntity(
|
||||
}
|
||||
|
||||
init {
|
||||
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, handler)
|
||||
exposeGlobally(Capabilities.ItemHandler.BLOCK, handler)
|
||||
savetablesLevel.stateful(::container, INVENTORY_KEY)
|
||||
}
|
||||
|
||||
override fun saveLevel(nbt: CompoundTag) {
|
||||
super.saveLevel(nbt)
|
||||
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveLevel(nbt, registry)
|
||||
lootTable?.let { nbt[LOOT_TABLE_KEY] = it.toString() }
|
||||
lootTableSeed?.let { nbt[LOOT_TABLE_SEED_KEY] = it }
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
lootTable = nbt.map(LOOT_TABLE_KEY) { it: StringTag -> ResourceLocation.tryParse(it.asString) }
|
||||
lootTableSeed = (nbt[LOOT_TABLE_SEED_KEY] as LongTag?)?.asLong
|
||||
}
|
||||
@ -105,7 +106,7 @@ class CargoCrateBlockEntity(
|
||||
val lootTableSeed = lootTableSeed ?: 0L
|
||||
val server = level?.server ?: return
|
||||
|
||||
val loot = server.lootData.getLootTable(lootTable)
|
||||
val loot = server.loot.getLootTable(lootTable)
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
CriteriaTriggers.GENERATE_LOOT.trigger(ply, lootTable)
|
||||
|
@ -2,14 +2,13 @@ package ru.dbotthepony.mc.otm.block.entity.decorative
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.IdMappingEvent
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.items.IItemHandler
|
||||
import net.neoforged.neoforge.registries.IdMappingEvent
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
import ru.dbotthepony.mc.otm.core.getID
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
|
||||
class DevChestBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.DEV_CHEST, blockPos, blockState), IItemHandler {
|
||||
@ -38,7 +37,7 @@ class DevChestBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryB
|
||||
}
|
||||
|
||||
init {
|
||||
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, this)
|
||||
exposeGlobally(Capabilities.ItemHandler.BLOCK, this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -52,8 +51,8 @@ class DevChestBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryB
|
||||
|
||||
val sorted = Int2ObjectAVLTreeMap<ItemStack>()
|
||||
|
||||
for (item in ForgeRegistries.ITEMS.values) {
|
||||
check(sorted.put(ForgeRegistries.ITEMS.getID(item), ItemStack(item, 1).also { it.count = item.getMaxStackSize(it) }) == null)
|
||||
for (item in BuiltInRegistries.ITEM) {
|
||||
check(sorted.put(BuiltInRegistries.ITEM.getId(item), ItemStack(item, 1).also { it.count = item.getMaxStackSize(it) }) == null)
|
||||
}
|
||||
|
||||
cache.addAll(sorted.values)
|
||||
|
@ -8,9 +8,9 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.fluids.FluidStack
|
||||
import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kommons.util.ListenableDelegate
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
@ -22,7 +22,6 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.core.util.FluidStackValueCodec
|
||||
import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
@ -47,10 +46,10 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
fillInput.handler(object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
if (fluid.isEmpty) {
|
||||
return stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).map { it.tanks > 0 }.orElse(false)
|
||||
return stack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.tanks > 0 } ?: false
|
||||
}
|
||||
|
||||
return stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).map { it.fill(fluid[0], IFluidHandler.FluidAction.SIMULATE) > 0 }.orElse(false)
|
||||
return stack.getCapability(Capabilities.FluidHandler.ITEM)?.let { it.fill(fluid[0], IFluidHandler.FluidAction.SIMULATE) > 0 } ?: false
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
|
||||
@ -80,7 +79,7 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
val item = drainInput[0]
|
||||
|
||||
if (item.isNotEmpty) {
|
||||
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull()
|
||||
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(Capabilities.FluidHandler.ITEM)
|
||||
|
||||
if (cap == null) {
|
||||
if (output.consumeItem(item, simulate = false)) {
|
||||
@ -106,7 +105,7 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
|
||||
if (moved0.isNotEmpty) {
|
||||
if (output.consumeItem(cap.container, simulate = true)) {
|
||||
val cap1 = item.copyWithCount(1).getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull() ?: throw ConcurrentModificationException()
|
||||
val cap1 = item.copyWithCount(1).getCapability(Capabilities.FluidHandler.ITEM) ?: throw ConcurrentModificationException()
|
||||
|
||||
val moved1 = moveFluid(source = cap1, destination = fluid)
|
||||
|
||||
@ -132,7 +131,7 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
val item = fillInput[0]
|
||||
|
||||
if (item.isNotEmpty) {
|
||||
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull()
|
||||
val cap = (if (item.count == 1) item else item.copyWithCount(1)).getCapability(Capabilities.FluidHandler.ITEM)
|
||||
|
||||
if (cap == null) {
|
||||
if (output.consumeItem(item, simulate = false)) {
|
||||
@ -158,7 +157,7 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
|
||||
if (moved0.isNotEmpty) {
|
||||
if (output.consumeItem(cap.container, simulate = true)) {
|
||||
val cap1 = item.copyWithCount(1).getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull() ?: throw ConcurrentModificationException()
|
||||
val cap1 = item.copyWithCount(1).getCapability(Capabilities.FluidHandler.ITEM) ?: throw ConcurrentModificationException()
|
||||
|
||||
val moved1 = moveFluid(source = fluid, destination = cap1)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.decorative
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
@ -86,8 +87,8 @@ class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryB
|
||||
}
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
|
||||
if (!isLocked)
|
||||
signText = truncate(signText)
|
||||
|
@ -3,11 +3,11 @@ package ru.dbotthepony.mc.otm.block.entity.decorative
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.fluids.FluidStack
|
||||
import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import java.util.function.Consumer
|
||||
|
||||
@ -45,18 +45,16 @@ class InfiniteWaterSourceBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
}
|
||||
|
||||
init {
|
||||
exposeGlobally(ForgeCapabilities.FLUID_HANDLER, this)
|
||||
exposeGlobally(Capabilities.FluidHandler.BLOCK, this)
|
||||
|
||||
for (side in sides.values) {
|
||||
val tracker = side.track(ForgeCapabilities.FLUID_HANDLER)
|
||||
for (side in RelativeSide.entries) {
|
||||
val tracker = CapabilityCache(side, Capabilities.FluidHandler.BLOCK)
|
||||
|
||||
val ticker = tickList.Ticker {
|
||||
tracker.get().ifPresentK {
|
||||
it.fill(FluidStack(Fluids.WATER, Int.MAX_VALUE), IFluidHandler.FluidAction.EXECUTE)
|
||||
}
|
||||
tracker.get()?.fill(FluidStack(Fluids.WATER, Int.MAX_VALUE), IFluidHandler.FluidAction.EXECUTE)
|
||||
}
|
||||
|
||||
tracker.addListener(Consumer { ticker.isEnabled = it.isPresent })
|
||||
tracker.addListener(Consumer { ticker.isEnabled = tracker.isPresent })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.decorative
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.datafixers.util.Either
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@ -15,13 +14,12 @@ import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.fluids.FluidStack
|
||||
import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.immutableMap
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
@ -85,7 +83,7 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
|
||||
addDroppableContainer(dyeInput)
|
||||
savetables.stateful(dyeInput, INVENTORY_KEY)
|
||||
savetables.bool(::isBulk)
|
||||
exposeGlobally(ForgeCapabilities.FLUID_HANDLER, this)
|
||||
exposeGlobally(Capabilities.FluidHandler.BLOCK, this)
|
||||
}
|
||||
|
||||
fun takeDyes(dyes: Map<out DyeColor?, Int>) {
|
||||
@ -113,7 +111,7 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
|
||||
val config = ConfigurableItemHandler(input = dyeInput.handler(object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
if (waterStored() < MAX_WATER_STORAGE) {
|
||||
stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresentK {
|
||||
stack.getCapability(Capabilities.FluidHandler.ITEM)?.let {
|
||||
val drain = it.drain(FluidStack(Fluids.WATER, MAX_WATER_STORAGE - waterStored()), IFluidHandler.FluidAction.SIMULATE)
|
||||
|
||||
if (drain.isNotEmpty) {
|
||||
@ -127,7 +125,7 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
|
||||
}
|
||||
|
||||
override fun modifyInsertCount(slot: Int, stack: ItemStack, existing: ItemStack, simulate: Boolean): Int {
|
||||
if (!stack.equals(existing, false))
|
||||
if (!ItemStack.isSameItemSameComponents(stack, existing))
|
||||
return super.modifyInsertCount(slot, stack, existing, simulate)
|
||||
|
||||
val dye = DyeColor.entries.firstOrNull { stack.`is`(it.tag) } ?: return 0
|
||||
@ -147,8 +145,8 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
|
||||
return dyeStored.getInt(dye)
|
||||
}
|
||||
|
||||
override fun saveShared(nbt: CompoundTag) {
|
||||
super.saveShared(nbt)
|
||||
override fun saveShared(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveShared(nbt, registry)
|
||||
|
||||
nbt["dyes"] = CompoundTag().also {
|
||||
for ((k, v) in dyeStored) {
|
||||
@ -157,8 +155,8 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
|
||||
}
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
|
||||
dyeStored.clear()
|
||||
|
||||
@ -177,7 +175,7 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
|
||||
|
||||
for (slot in dyeInput.slotIterator()) {
|
||||
if (waterStored() < MAX_WATER_STORAGE) {
|
||||
slot.item.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresentK {
|
||||
slot.item.getCapability(Capabilities.FluidHandler.ITEM)?.let {
|
||||
val drain = it.drain(FluidStack(Fluids.WATER, MAX_WATER_STORAGE - waterStored()), IFluidHandler.FluidAction.EXECUTE)
|
||||
|
||||
if (drain.isNotEmpty) {
|
||||
|
@ -81,13 +81,13 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
|
||||
val bottlingHandler = bottling.handler(object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
return isBottling && stack.getCapability(MatteryCapability.MATTER).map { it.matterFlow.input && it.missingMatter.isPositive }.orElse(false)
|
||||
return isBottling && stack.getCapability(MatteryCapability.MATTER_ITEM)?.let { it.matterFlow.input && it.missingMatter.isPositive } ?: false
|
||||
}
|
||||
})
|
||||
|
||||
val unbottlingHandler = unbottling.handler(object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
return !isBottling && stack.getCapability(MatteryCapability.MATTER).map { it.matterFlow.output && it.storedMatter.isPositive }.orElse(false)
|
||||
return !isBottling && stack.getCapability(MatteryCapability.MATTER_ITEM)?.let { it.matterFlow.output && it.storedMatter.isPositive } ?: false
|
||||
}
|
||||
})
|
||||
|
||||
@ -109,7 +109,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
val matterNode = SimpleMatterNode(matter = matter)
|
||||
|
||||
init {
|
||||
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
|
||||
savetables.bool(::isBottling)
|
||||
@ -145,7 +145,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
var state = blockState
|
||||
|
||||
for (i in 0 .. 2) {
|
||||
val desired = !container.getItem(i).isEmpty && container.getItem(i).getCapability(MatteryCapability.MATTER).isPresent
|
||||
val desired = !container.getItem(i).isEmpty && container.getItem(i).getCapability(MatteryCapability.MATTER_ITEM) != null
|
||||
|
||||
if (state.getValue(MatterBottlerBlock.SLOT_PROPERTIES[i]) != desired) {
|
||||
state = state.setValue(MatterBottlerBlock.SLOT_PROPERTIES[i], desired)
|
||||
@ -190,7 +190,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
|
||||
for (slot in bottling.slotIterator()) {
|
||||
val item = slot.item
|
||||
item.getCapability(MatteryCapability.MATTER).ifPresentK {
|
||||
item.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
if (!it.missingMatter.isPositive) {
|
||||
unbottling.consumeItem(item, false)
|
||||
slot.setChanged()
|
||||
@ -256,7 +256,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
for (slot in unbottling.slotIterator()) {
|
||||
val item = slot.item
|
||||
|
||||
item.getCapability(MatteryCapability.MATTER).ifPresentK {
|
||||
item.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
if (!it.storedMatter.isPositive) {
|
||||
bottling.consumeItem(item, false)
|
||||
slot.setChanged()
|
||||
|
@ -19,7 +19,6 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
||||
import ru.dbotthepony.mc.otm.menu.matter.MatterCapacitorBankMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
@ -39,7 +38,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
||||
|
||||
for (stack in container)
|
||||
if (!stack.isEmpty)
|
||||
stack.getCapability(MatteryCapability.MATTER).ifPresentK {
|
||||
stack.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
summ += it.storedMatter
|
||||
}
|
||||
|
||||
@ -55,7 +54,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
||||
|
||||
for (stack in container)
|
||||
if (!stack.isEmpty)
|
||||
stack.getCapability(MatteryCapability.MATTER).ifPresentK {
|
||||
stack.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
summ += it.maxStoredMatter
|
||||
}
|
||||
|
||||
@ -72,7 +71,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
||||
|
||||
for (stack in container) {
|
||||
if (!stack.isEmpty) {
|
||||
stack.getCapability(MatteryCapability.MATTER).ifPresent {
|
||||
stack.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
val diff = it.receiveMatterChecked(howMuch, simulate)
|
||||
summ += diff
|
||||
howMuch -= diff
|
||||
@ -101,7 +100,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
||||
|
||||
for (stack in container) {
|
||||
if (!stack.isEmpty) {
|
||||
stack.getCapability(MatteryCapability.MATTER).ifPresent {
|
||||
stack.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
val diff = it.extractMatterChecked(howMuch, simulate)
|
||||
summ += diff
|
||||
howMuch -= diff
|
||||
@ -123,10 +122,10 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
||||
override val matterFlow: FlowDirection
|
||||
get() = FlowDirection.BI_DIRECTIONAL
|
||||
|
||||
val container = object : MatteryContainer(this::markDirtyFast, BatteryBankBlockEntity.CAPACITY) {
|
||||
val container = object : MatteryContainer(::markDirtyFast, BatteryBankBlockEntity.CAPACITY) {
|
||||
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
|
||||
super.setChanged(slot, new, old)
|
||||
capacitorStatus[slot].value = new.getCapability(MatteryCapability.MATTER).isPresent
|
||||
capacitorStatus[slot].value = new.getCapability(MatteryCapability.MATTER_ITEM) != null
|
||||
gaugeLevel = storedMatter.percentage(maxStoredMatter)
|
||||
}
|
||||
|
||||
@ -135,11 +134,11 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
||||
|
||||
val itemConfig = ConfigurableItemHandler(inputOutput = container.handler(object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
return stack.getCapability(MatteryCapability.MATTER).isPresent
|
||||
return stack.getCapability(MatteryCapability.MATTER_ITEM) != null
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
|
||||
stack.getCapability(MatteryCapability.MATTER).ifPresentK {
|
||||
stack.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
if (it.storedMatter.isPositive) {
|
||||
return false
|
||||
}
|
||||
@ -155,7 +154,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
||||
|
||||
init {
|
||||
savetables.stateful(::container, INVENTORY_KEY)
|
||||
exposeGlobally(MatteryCapability.MATTER, this)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, this)
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
|
||||
val matterNode = SimpleMatterNode(matter = matter)
|
||||
|
||||
init {
|
||||
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
savetables.stateful(::matter, MATTER_STORAGE_KEY)
|
||||
}
|
||||
|
@ -7,9 +7,10 @@ import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.CraftingInput
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage
|
||||
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||
import ru.dbotthepony.mc.otm.block.entity.JobContainer
|
||||
@ -26,7 +27,6 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.MatteryCraftingContainer
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer
|
||||
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||
@ -75,12 +75,13 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
|
||||
val itemConfig = ConfigurableItemHandler(
|
||||
input = inputs.handler(object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
val shadow = ShadowCraftingContainer.shadow(inputs, slot, stack)
|
||||
val list = inputs.toList()
|
||||
list[slot] = stack
|
||||
val shadow = CraftingInput.of(3, 3, list)
|
||||
|
||||
return (level ?: return false)
|
||||
.recipeManager
|
||||
.byType(MRecipes.MATTER_ENTANGLER)
|
||||
.values
|
||||
.any { it.value.preemptivelyMatches(shadow, level!!) }
|
||||
}
|
||||
|
||||
@ -92,7 +93,7 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
|
||||
)
|
||||
|
||||
init {
|
||||
exposeGlobally(ForgeCapabilities.FLUID_HANDLER, experience)
|
||||
exposeGlobally(Capabilities.FluidHandler.BLOCK, experience)
|
||||
|
||||
savetables.stateful(::energy, ENERGY_KEY)
|
||||
savetables.stateful(::matter, MATTER_STORAGE_KEY)
|
||||
@ -102,7 +103,7 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
|
||||
savetables.stateful(::experience)
|
||||
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, node)
|
||||
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
|
||||
}
|
||||
|
||||
override fun setLevel(level: Level) {
|
||||
@ -144,16 +145,17 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
|
||||
if (!energy.batteryLevel.isPositive)
|
||||
return JobContainer.noEnergy()
|
||||
|
||||
val inputs = CraftingInput.of(3, 3, inputs.toList())
|
||||
|
||||
val recipe = (level ?: return JobContainer.failure())
|
||||
.recipeManager
|
||||
.byType(MRecipes.MATTER_ENTANGLER)
|
||||
.values
|
||||
.firstOrNull { it.value.matches(inputs, level!!) } ?: return JobContainer.noItem()
|
||||
|
||||
val result = recipe.value.assemble(inputs, level!!.registryAccess())
|
||||
|
||||
inputs.forEach { it.shrink(1) }
|
||||
inputs.setChanged()
|
||||
this.inputs.forEach { it.shrink(1) }
|
||||
this.inputs.setChanged()
|
||||
|
||||
return JobContainer.success(
|
||||
Job(
|
||||
|
@ -3,27 +3,28 @@ package ru.dbotthepony.mc.otm.block.entity.matter
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.matter.*
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider
|
||||
import ru.dbotthepony.mc.otm.capability.matter.PatternState
|
||||
import ru.dbotthepony.mc.otm.capability.matter.ReplicationTask
|
||||
import ru.dbotthepony.mc.otm.capability.matter.ReplicationTaskAllocation
|
||||
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
|
||||
import ru.dbotthepony.mc.otm.core.nbt.getBoolean
|
||||
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||
import ru.dbotthepony.mc.otm.core.nbt.mapString
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.util.ItemSorter
|
||||
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
||||
import ru.dbotthepony.mc.otm.menu.IItemSortingSettings
|
||||
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
@ -81,7 +82,7 @@ class MatterPanelBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
|
||||
init {
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
exposeGlobally(MatteryCapability.TASK, this)
|
||||
exposeGlobally(MatteryCapability.REPLICATION_TASK, this)
|
||||
|
||||
savetables.bool(::isProvidingTasks)
|
||||
}
|
||||
@ -149,8 +150,8 @@ class MatterPanelBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
return true
|
||||
}
|
||||
|
||||
override fun saveShared(nbt: CompoundTag) {
|
||||
super.saveShared(nbt)
|
||||
override fun saveShared(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveShared(nbt, registry)
|
||||
|
||||
val list = ListTag()
|
||||
|
||||
@ -163,14 +164,14 @@ class MatterPanelBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
val settings = CompoundTag()
|
||||
|
||||
for ((uuid, value) in playerSettings) {
|
||||
settings[uuid.toString()] = value.serializeNBT()
|
||||
settings[uuid.toString()] = value.serializeNBT(registry)
|
||||
}
|
||||
|
||||
nbt["settings"] = settings
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
_tasks.clear()
|
||||
val list = nbt.getCompoundList("tasks")
|
||||
|
||||
@ -186,8 +187,9 @@ class MatterPanelBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
|
||||
nbt.map("settings") { it: CompoundTag ->
|
||||
for (k in it.allKeys) {
|
||||
playerSettings.computeIfAbsent(UUID.fromString(k), Object2ObjectFunction { PlayerSettings() })
|
||||
.deserializeNBT(it.getCompound(k))
|
||||
playerSettings
|
||||
.computeIfAbsent(UUID.fromString(k), Object2ObjectFunction { PlayerSettings() })
|
||||
.deserializeNBT(registry, it.getCompound(k))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.matter
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
@ -10,7 +11,6 @@ import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
|
||||
@ -78,7 +78,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
}
|
||||
|
||||
init {
|
||||
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
|
||||
savetables.stateful(::repairContainer)
|
||||
@ -92,7 +92,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
|
||||
savetables.Stateless(::lastItem, type = StringTag::class.java)
|
||||
.withSerializer { it?.registryName?.toString()?.let(StringTag::valueOf) }
|
||||
.withDeserializer { ResourceLocation.tryParse(it.asString)?.let { ForgeRegistries.ITEMS.getValue(it) } }
|
||||
.withDeserializer { ResourceLocation.tryParse(it.asString)?.let { BuiltInRegistries.ITEM.get(it) } }
|
||||
}
|
||||
|
||||
val energyConfig = ConfigurableEnergy(energy)
|
||||
|
@ -66,7 +66,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
val energyConfig = ConfigurableEnergy(energy)
|
||||
|
||||
init {
|
||||
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
|
||||
savetables.stateful(::energy, ENERGY_KEY)
|
||||
|
@ -30,7 +30,6 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.util.item
|
||||
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||
import ru.dbotthepony.mc.otm.data.UUIDCodec
|
||||
import ru.dbotthepony.mc.otm.data.minRange
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
@ -96,7 +95,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
}
|
||||
|
||||
init {
|
||||
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
|
||||
savetables.stateful(::energy, ENERGY_KEY)
|
||||
|
@ -72,11 +72,6 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
savetables.stateful(::upgrades)
|
||||
}
|
||||
|
||||
override fun invalidateCaps() {
|
||||
super.invalidateCaps()
|
||||
matterNode.isValid = false
|
||||
}
|
||||
|
||||
override fun setRemoved() {
|
||||
super.setRemoved()
|
||||
matterNode.isValid = false
|
||||
|
@ -19,7 +19,6 @@ import ru.dbotthepony.mc.otm.core.collect.filterNotNull
|
||||
import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.filterNotNull
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import java.util.stream.Stream
|
||||
@ -29,17 +28,17 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
|
||||
val matterNode = SimpleMatterNode(patterns = this)
|
||||
|
||||
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 8) {
|
||||
val container: MatteryContainer = object : MatteryContainer(::markDirtyFast, 8) {
|
||||
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
|
||||
if (!ItemStack.isSameItemSameTags(new, old)) {
|
||||
if (!ItemStack.isSameItemSameComponents(new, old)) {
|
||||
if (!old.isEmpty) {
|
||||
old.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
|
||||
old.getCapability(MatteryCapability.PATTERN_ITEM)?.let { cap: IPatternStorage ->
|
||||
cap.patterns.forEach { matterNode.graph.onPatternRemoved(it) }
|
||||
}
|
||||
}
|
||||
|
||||
if (!new.isEmpty) {
|
||||
new.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
|
||||
new.getCapability(MatteryCapability.PATTERN_ITEM)?.let { cap: IPatternStorage ->
|
||||
cap.patterns.forEach { matterNode.graph.onPatternAdded(it) }
|
||||
}
|
||||
}
|
||||
@ -61,7 +60,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
for (i in 0..7) {
|
||||
state = state.setValue(
|
||||
PatternStorageBlock.PATTERN_STORAGE_DISKS_PROPS[i],
|
||||
this.container.getItem(i).getCapability(MatteryCapability.PATTERN).isPresent
|
||||
this.container.getItem(i).getCapability(MatteryCapability.PATTERN_ITEM) != null
|
||||
)
|
||||
}
|
||||
|
||||
@ -77,13 +76,8 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
matterNode.discover(this)
|
||||
}
|
||||
|
||||
override fun invalidateCaps() {
|
||||
super.invalidateCaps()
|
||||
matterNode.isValid = false
|
||||
}
|
||||
|
||||
init {
|
||||
exposeGlobally(MatteryCapability.PATTERN, this)
|
||||
exposeGlobally(MatteryCapability.PATTERN_BLOCK, this)
|
||||
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
|
||||
|
||||
savetables.stateful(::container, INVENTORY_KEY)
|
||||
@ -96,7 +90,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
override val patterns: Stream<PatternState> get() {
|
||||
return container.stream()
|
||||
.filter { it.isNotEmpty }
|
||||
.map { it.getCapability(MatteryCapability.PATTERN).orNull() }
|
||||
.map { it.getCapability(MatteryCapability.PATTERN_ITEM) }
|
||||
.filterNotNull()
|
||||
.flatMap { it.patterns }
|
||||
}
|
||||
@ -104,7 +98,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
override val patternCapacity: Int get() {
|
||||
var stored = 0L
|
||||
|
||||
for (pattern in this.container.iterator().map { it.getCapability(MatteryCapability.PATTERN).orNull() }.filterNotNull())
|
||||
for (pattern in this.container.iterator().map { it.getCapability(MatteryCapability.PATTERN_ITEM) }.filterNotNull())
|
||||
stored += pattern.patternCapacity.toLong()
|
||||
|
||||
return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt()
|
||||
@ -113,7 +107,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
override val storedPatterns: Int get() {
|
||||
var stored = 0L
|
||||
|
||||
for (pattern in this.container.iterator().map { it.getCapability(MatteryCapability.PATTERN).orNull() }.filterNotNull())
|
||||
for (pattern in this.container.iterator().map { it.getCapability(MatteryCapability.PATTERN_ITEM) }.filterNotNull())
|
||||
stored += pattern.storedPatterns.toLong()
|
||||
|
||||
return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt()
|
||||
@ -125,7 +119,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
}
|
||||
|
||||
override fun insertPattern(pattern: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
|
||||
for (spattern in this.container.iterator().map { it.getCapability(MatteryCapability.PATTERN).orNull() }.filterNotNull()) {
|
||||
for (spattern in this.container.iterator().map { it.getCapability(MatteryCapability.PATTERN_ITEM) }.filterNotNull()) {
|
||||
val status = spattern.insertPattern(pattern, onlyUpdate, simulate)
|
||||
|
||||
if (!status.isFailed) {
|
||||
|
@ -15,7 +15,6 @@ import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.menu.storage.DriveRackMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.storage.optics.priority
|
||||
@ -46,15 +45,15 @@ class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
markDirtyFast()
|
||||
}
|
||||
|
||||
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 4) {
|
||||
val container: MatteryContainer = object : MatteryContainer(::markDirtyFast, 4) {
|
||||
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
|
||||
super.setChanged(slot, new, old)
|
||||
|
||||
old.getCapability(MatteryCapability.DRIVE).ifPresentK {
|
||||
old.getCapability(MatteryCapability.CONDENSATION_DRIVE)?.let {
|
||||
cell.removeStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy).flow(::mode))
|
||||
}
|
||||
|
||||
new.getCapability(MatteryCapability.DRIVE).ifPresentK {
|
||||
new.getCapability(MatteryCapability.CONDENSATION_DRIVE)?.let {
|
||||
cell.addStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy).flow(::mode))
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class DriveViewerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyUpdated, MachinesConfig.DRIVE_VIEWER))
|
||||
val energyConfig = ConfigurableEnergy(energy)
|
||||
|
||||
val container: MatteryContainer = object : MatteryContainer(this::markDirtyFast, 1) {
|
||||
val container: MatteryContainer = object : MatteryContainer(::markDirtyFast, 1) {
|
||||
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
|
||||
super.setChanged(slot, new, old)
|
||||
|
||||
@ -37,7 +37,7 @@ class DriveViewerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
|
||||
if (level is ServerLevel) {
|
||||
tickList.once {
|
||||
val isPresent = new.getCapability(MatteryCapability.DRIVE).isPresent
|
||||
val isPresent = new.getCapability(MatteryCapability.CONDENSATION_DRIVE) != null
|
||||
var state = this@DriveViewerBlockEntity.blockState.setValue(DriveViewerBlock.DRIVE_PRESENT, isPresent)
|
||||
|
||||
if (!isPresent) {
|
||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.block.entity.storage
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
@ -11,15 +12,13 @@ import net.minecraft.world.Container
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.TransientCraftingContainer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.CraftingRecipe
|
||||
import net.minecraft.world.item.crafting.RecipeType
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.ForgeHooks
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import net.neoforged.neoforge.common.CommonHooks
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||
@ -27,28 +26,35 @@ import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
|
||||
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets8
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.container.set
|
||||
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
||||
import ru.dbotthepony.mc.otm.container.MatteryCraftingContainer
|
||||
import ru.dbotthepony.mc.otm.container.util.slotIterator
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.collect.toList
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.nbt.mapString
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
|
||||
import ru.dbotthepony.mc.otm.menu.storage.ItemMonitorMenu
|
||||
import ru.dbotthepony.mc.otm.storage.*
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageEventConsumer
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageProvider
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStorageStack
|
||||
import ru.dbotthepony.mc.otm.storage.StorageStack
|
||||
import ru.dbotthepony.mc.otm.storage.powered.PoweredVirtualComponent
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets8
|
||||
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
||||
import ru.dbotthepony.mc.otm.container.MatteryCraftingContainer
|
||||
import ru.dbotthepony.mc.otm.container.util.slotIterator
|
||||
import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.collect.toList
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.indices
|
||||
import kotlin.collections.iterator
|
||||
import kotlin.collections.set
|
||||
|
||||
interface IItemMonitorPlayerSettings {
|
||||
var ingredientPriority: ItemMonitorPlayerSettings.IngredientPriority
|
||||
@ -64,7 +70,7 @@ private fun takeOne(inventory: Container?, item: ItemStack): Boolean {
|
||||
for (slot in iterator) {
|
||||
val stack = slot.item
|
||||
|
||||
if (stack.equals(item, false)) {
|
||||
if (ItemStack.isSameItemSameComponents(stack, item)) {
|
||||
stack.shrink(1)
|
||||
slot.setChanged()
|
||||
return true
|
||||
@ -154,7 +160,7 @@ class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag>, IItemMonitorPla
|
||||
override var sorting: ItemStorageStackSorter = ItemStorageStackSorter.DEFAULT
|
||||
override var ascendingSort: Boolean = false
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return CompoundTag().also {
|
||||
it["ingredientPriority"] = ingredientPriority.name
|
||||
it["resultTarget"] = resultTarget.name
|
||||
@ -164,7 +170,7 @@ class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag>, IItemMonitorPla
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag) {
|
||||
ingredientPriority = nbt.mapString("ingredientPriority", IngredientPriority::valueOf, IngredientPriority.SYSTEM)
|
||||
resultTarget = nbt.mapString("resultTarget", ResultTarget::valueOf, ResultTarget.MIXED)
|
||||
craftingAmount = nbt.mapString("quickCraftAmount", Amount::valueOf, Amount.STACK)
|
||||
@ -227,10 +233,10 @@ class ItemMonitorBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
val server = level.server ?: return false
|
||||
|
||||
var craftingRecipe = craftingRecipe
|
||||
if (craftingRecipe != null && craftingRecipe.matches(craftingGrid, level)) return true
|
||||
if (craftingRecipe != null && craftingRecipe.matches(craftingGrid.asCraftInput(), level)) return true
|
||||
if (justCheckForRecipeChange) return false
|
||||
|
||||
craftingRecipe = server.recipeManager.getRecipeFor(RecipeType.CRAFTING, craftingGrid, level).orElse(null)?.value
|
||||
craftingRecipe = server.recipeManager.getRecipeFor(RecipeType.CRAFTING, craftingGrid.asCraftInput(), level).orElse(null)?.value
|
||||
Arrays.fill(craftingGridTuples, null)
|
||||
val poweredView = poweredView
|
||||
|
||||
@ -303,13 +309,14 @@ class ItemMonitorBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
val craftingPlayer = craftingPlayer ?: return ItemStack.EMPTY
|
||||
|
||||
try {
|
||||
ForgeHooks.setCraftingPlayer(craftingPlayer)
|
||||
CommonHooks.setCraftingPlayer(craftingPlayer)
|
||||
|
||||
if (craftingRecipe.getResultItem(level.registryAccess()).count != amount) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
} finally {
|
||||
ForgeHooks.setCraftingPlayer(null)
|
||||
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
||||
CommonHooks.setCraftingPlayer(null)
|
||||
}
|
||||
|
||||
craftingAmount[craftingPlayer] = craftingAmount.getInt(craftingPlayer) + 1
|
||||
@ -325,15 +332,16 @@ class ItemMonitorBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
inProcessOfCraft = true
|
||||
|
||||
try {
|
||||
ForgeHooks.setCraftingPlayer(craftingPlayer)
|
||||
CommonHooks.setCraftingPlayer(craftingPlayer)
|
||||
val residue: NonNullList<ItemStack>
|
||||
val result: ItemStack
|
||||
|
||||
try {
|
||||
residue = craftingRecipe.getRemainingItems(craftingGrid)
|
||||
residue = craftingRecipe.getRemainingItems(craftingGrid.asCraftInput())
|
||||
result = craftingRecipe.getResultItem(level.registryAccess())
|
||||
} finally {
|
||||
ForgeHooks.setCraftingPlayer(null)
|
||||
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
||||
CommonHooks.setCraftingPlayer(null)
|
||||
}
|
||||
|
||||
check(residue.size == craftingGrid.containerSize) { "Container and residue list sizes mismatch: ${residue.size} != ${craftingGrid.containerSize}" }
|
||||
@ -408,29 +416,29 @@ class ItemMonitorBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
|
||||
|
||||
val craftingResultContainer = CraftingResultContainer()
|
||||
|
||||
override fun saveLevel(nbt: CompoundTag) {
|
||||
super.saveLevel(nbt)
|
||||
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveLevel(nbt, registry)
|
||||
|
||||
nbt.put("player_settings", CompoundTag().also {
|
||||
for ((key, value) in this.settings) {
|
||||
it[key.toString()] = value.serializeNBT()
|
||||
it[key.toString()] = value.serializeNBT(registry)
|
||||
}
|
||||
})
|
||||
|
||||
nbt["crafting_grid"] = craftingGrid.serializeNBT()
|
||||
nbt["crafting_grid"] = craftingGrid.serializeNBT(registry)
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
this.settings.clear()
|
||||
|
||||
val settings = nbt.getCompound("player_settings")
|
||||
|
||||
for (key in settings.allKeys) {
|
||||
check(this.settings.put(UUID.fromString(key), ItemMonitorPlayerSettings().also { it.deserializeNBT(settings.getCompound(key)) }) == null)
|
||||
check(this.settings.put(UUID.fromString(key), ItemMonitorPlayerSettings().also { it.deserializeNBT(registry, settings.getCompound(key)) }) == null)
|
||||
}
|
||||
|
||||
craftingGrid.deserializeNBT(nbt["crafting_grid"])
|
||||
craftingGrid.deserializeNBT(registry, nbt["crafting_grid"])
|
||||
}
|
||||
|
||||
fun getSettings(ply: ServerPlayer): ItemMonitorPlayerSettings {
|
||||
|
@ -12,8 +12,8 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.items.IItemHandler
|
||||
import ru.dbotthepony.mc.otm.*
|
||||
import ru.dbotthepony.mc.otm.block.CableBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
|
||||
@ -102,10 +102,10 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
savetables.int(::extractPriority)
|
||||
exposeGlobally(MatteryCapability.STORAGE_NODE, cell) { it != RelativeSide.FRONT }
|
||||
|
||||
side(RelativeSide.FRONT).track(ForgeCapabilities.ITEM_HANDLER).addListener(Consumer {
|
||||
CapabilityCache(RelativeSide.FRONT, Capabilities.ItemHandler.BLOCK).addListener(Consumer {
|
||||
component?.let(cell::removeStorageComponent)
|
||||
component = if (it.isPresent) {
|
||||
ItemHandlerComponent(it.orThrow()).also { if (!redstoneControl.isBlockedByRedstone) cell.addStorageComponent(it) }
|
||||
component = if (it != null) {
|
||||
ItemHandlerComponent(it).also { if (!redstoneControl.isBlockedByRedstone) cell.addStorageComponent(it) }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@ -353,7 +353,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
} else if (current != null && last == null) {
|
||||
addTracked(slot, current)
|
||||
} else if (current != null && last != null) {
|
||||
if (!ItemStack.isSameItemSameTags(current, last)) {
|
||||
if (!ItemStack.isSameItemSameComponents(current, last)) {
|
||||
removeTracked(slot)
|
||||
addTracked(slot, current)
|
||||
} else if (current.count != last.count) {
|
||||
|
@ -11,8 +11,8 @@ import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.items.IItemHandler
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
|
||||
import ru.dbotthepony.mc.otm.block.CableBlock
|
||||
@ -27,7 +27,6 @@ import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
|
||||
import ru.dbotthepony.mc.otm.menu.storage.StorageImporterExporterMenu
|
||||
import ru.dbotthepony.mc.otm.once
|
||||
@ -39,7 +38,6 @@ import ru.dbotthepony.mc.otm.storage.ItemStorageStack
|
||||
import ru.dbotthepony.mc.otm.storage.StorageStack
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
abstract class AbstractStorageImportExport(
|
||||
blockType: BlockEntityType<*>,
|
||||
@ -97,7 +95,7 @@ abstract class AbstractStorageImportExport(
|
||||
cell.discover(this)
|
||||
}
|
||||
|
||||
protected val target = front.track(ForgeCapabilities.ITEM_HANDLER)
|
||||
protected val target = CapabilityCache(RelativeSide.FRONT, Capabilities.ItemHandler.BLOCK)
|
||||
|
||||
abstract val filter: ItemFilter
|
||||
|
||||
@ -122,7 +120,7 @@ class StorageImporterBlockEntity(
|
||||
private var nextTick = INTERVAL
|
||||
|
||||
init {
|
||||
front.Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
||||
exposeSided(RelativeSide.FRONT, Capabilities.ItemHandler.BLOCK, this)
|
||||
}
|
||||
|
||||
override fun getSlots(): Int {
|
||||
@ -190,7 +188,7 @@ class StorageImporterBlockEntity(
|
||||
|
||||
nextTick--
|
||||
|
||||
val target = target.get().orNull()
|
||||
val target = target.get()
|
||||
|
||||
if (nextTick <= 0 && target != null) {
|
||||
if (lastSlot >= target.slots) {
|
||||
@ -280,7 +278,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
|
||||
nextTick--
|
||||
|
||||
val target = target.get().orNull()
|
||||
val target = target.get()
|
||||
|
||||
if (nextTick <= 0 && target != null) {
|
||||
val items = cell.graph.getVirtualComponent(StorageStack.ITEMS)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.tech
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntList
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
@ -9,19 +10,19 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.AbstractCookingRecipe
|
||||
import net.minecraft.world.item.crafting.BlastingRecipe
|
||||
import net.minecraft.world.item.crafting.RecipeType
|
||||
import net.minecraft.world.item.crafting.SingleRecipeInput
|
||||
import net.minecraft.world.item.crafting.SmeltingRecipe
|
||||
import net.minecraft.world.item.crafting.SmokingRecipe
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage
|
||||
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||
import ru.dbotthepony.mc.otm.block.entity.JobContainer
|
||||
import ru.dbotthepony.mc.otm.block.entity.JobStatus
|
||||
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.item.CombinedItemHandler
|
||||
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
||||
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
@ -34,7 +35,6 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.container.balance
|
||||
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
import ru.dbotthepony.mc.otm.core.getValue
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.util.item
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
|
||||
@ -55,12 +55,12 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
||||
final override val upgrades = UpgradeContainer(this::markDirtyFast, 2, UpgradeType.BASIC_PROCESSING)
|
||||
final override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config)))
|
||||
|
||||
val inputs = immutableList(maxJobs) { MatteryContainer(this::itemContainerUpdated, 1) }
|
||||
val outputs = immutableList(maxJobs) { MatteryContainer(this::itemContainerUpdated, 1) }
|
||||
val inputs = MatteryContainer(this::itemContainerUpdated, maxJobs)
|
||||
val outputs = MatteryContainer(this::itemContainerUpdated, maxJobs)
|
||||
|
||||
init {
|
||||
inputs.forEach { addDroppableContainer(it) }
|
||||
outputs.forEach { addDroppableContainer(it) }
|
||||
addDroppableContainer(inputs)
|
||||
addDroppableContainer(outputs)
|
||||
}
|
||||
|
||||
inner class SyncSlot {
|
||||
@ -77,13 +77,13 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
||||
val experience = ExperienceStorage(config::maxExperienceStored).also(::addNeighbourListener)
|
||||
val energyConfig = ConfigurableEnergy(energy)
|
||||
val itemConfig = ConfigurableItemHandler(
|
||||
input = CombinedItemHandler(inputs.map { it.handler(HandlerFilter.OnlyIn) }),
|
||||
output = CombinedItemHandler(outputs.map { it.handler(HandlerFilter.OnlyOut) }),
|
||||
input = inputs.handler(HandlerFilter.OnlyIn),
|
||||
output = outputs.handler(HandlerFilter.OnlyOut),
|
||||
battery = batteryItemHandler
|
||||
)
|
||||
|
||||
init {
|
||||
exposeGlobally(ForgeCapabilities.FLUID_HANDLER, experience)
|
||||
exposeGlobally(Capabilities.FluidHandler.BLOCK, experience)
|
||||
|
||||
savetables.stateful(::upgrades)
|
||||
savetables.stateful(::energy)
|
||||
@ -105,7 +105,7 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
||||
}
|
||||
|
||||
override fun onJobFinish(status: JobStatus<ItemJob>, id: Int) {
|
||||
if (outputs[id].fullyAddItem(status.job.itemStack)) {
|
||||
if (outputs.fullyAddItem(status.job.itemStack, slots = IntList.of(id))) {
|
||||
experience.storeExperience(status.experience, this)
|
||||
syncSlots[id].inputItem = ItemStack.EMPTY
|
||||
syncSlots[id].outputItem = ItemStack.EMPTY
|
||||
@ -132,16 +132,22 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
||||
if (secondaryRecipeType != null) {
|
||||
val recipe = level.recipeManager
|
||||
.byType(secondaryRecipeType)
|
||||
.values
|
||||
.iterator()
|
||||
.filter { it.value.matches(inputs[id], 0) }
|
||||
.filter { it.value.matches(SingleRecipeInput(inputs[id]), level) }
|
||||
.maybe()?.value
|
||||
|
||||
if (recipe != null) {
|
||||
val toProcess = inputs[id][0].count.coerceAtMost(1 + upgrades.processingItems)
|
||||
val toProcess = inputs[id].count.coerceAtMost(1 + upgrades.processingItems)
|
||||
|
||||
inputs[id][0].shrink(toProcess)
|
||||
inputs[id].setChanged(id)
|
||||
val output = recipe.getResultItem(level.registryAccess()).copyWithCount(toProcess)
|
||||
val inputItem = inputs[id].copyWithCount(1)
|
||||
|
||||
inputs[id].shrink(toProcess)
|
||||
inputs.setChanged(id)
|
||||
|
||||
syncSlots[id].inputItem = inputItem
|
||||
syncSlots[id].outputItem = output.copy()
|
||||
syncSlots[id].progress = 0f
|
||||
|
||||
return JobContainer.success(
|
||||
ItemJob(
|
||||
@ -152,11 +158,11 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
|
||||
}
|
||||
}
|
||||
|
||||
return level.recipeManager.getRecipeFor(recipeType, inputs[id], level).map {
|
||||
val output = it.value.assemble(inputs[id], level.registryAccess())
|
||||
val inputItem = inputs[id][0].copyWithCount(1)
|
||||
val toProcess = inputs[id][0].count.coerceAtMost(upgrades.processingItems + 1)
|
||||
inputs[id][0].shrink(toProcess)
|
||||
return level.recipeManager.getRecipeFor(recipeType, SingleRecipeInput(inputs[id]), level).map {
|
||||
val output = it.value.assemble(SingleRecipeInput(inputs[id]), level.registryAccess())
|
||||
val inputItem = inputs[id].copyWithCount(1)
|
||||
val toProcess = inputs[id].count.coerceAtMost(upgrades.processingItems + 1)
|
||||
inputs[id].shrink(toProcess)
|
||||
|
||||
syncSlots[id].inputItem = inputItem
|
||||
syncSlots[id].outputItem = output.copy()
|
||||
|
@ -44,7 +44,7 @@ class AndroidChargerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
||||
ents.sort()
|
||||
|
||||
for ((ent) in ents) {
|
||||
val ply = ent.matteryPlayer ?: continue
|
||||
val ply = (ent as Player).matteryPlayer
|
||||
|
||||
if (ply.isAndroid) {
|
||||
val received = ply.androidEnergy.receiveEnergyChecked(available, false)
|
||||
|
@ -11,13 +11,13 @@ import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.AABB
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.WorkerState
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.capability.moveEnergy
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
|
||||
@ -81,10 +81,8 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
val z = blockPos.z.toDouble()
|
||||
|
||||
for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0))) {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
if (it.isAndroid)
|
||||
moveEnergy(energy, it.androidEnergy, amount = energy.batteryLevel, simulate = false, ignoreFlowRestrictions = true)
|
||||
}
|
||||
if (ent.matteryPlayer.isAndroid)
|
||||
moveEnergy(energy, ent.matteryPlayer.androidEnergy, amount = energy.batteryLevel, simulate = false, ignoreFlowRestrictions = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,14 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.bus.api.SubscribeEvent
|
||||
import net.neoforged.fml.common.EventBusSubscriber
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.kommons.util.value
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.capability.energy
|
||||
@ -35,7 +39,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
|
||||
val container: MatteryContainer = object : MatteryContainer(::setChanged, CAPACITY) {
|
||||
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
|
||||
super.setChanged(slot, new, old)
|
||||
batteryStatus[slot].value = new.getCapability(ForgeCapabilities.ENERGY).isPresent
|
||||
batteryStatus[slot].value = new.getCapability(Capabilities.EnergyStorage.ITEM) != null
|
||||
gaugeLevel = batteryLevel.percentage(maxBatteryLevel)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.ForgeHooks
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.WorkerState
|
||||
import ru.dbotthepony.mc.otm.capability.*
|
||||
@ -89,7 +88,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
|
||||
|
||||
if (workTicks == 0 && !redstoneControl.isBlockedByRedstone && checkFuelSlot) {
|
||||
if (!fuelContainer[0].isEmpty) {
|
||||
val ticks = ForgeHooks.getBurnTime(fuelContainer[0], null) / MachinesConfig.ChemicalGenerator.RATIO
|
||||
val ticks = fuelContainer[0].getBurnTime(null) / MachinesConfig.ChemicalGenerator.RATIO
|
||||
|
||||
if (
|
||||
ticks > 0 &&
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.tech
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.IntTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
@ -9,7 +10,7 @@ import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.kommons.util.setValue
|
||||
import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
|
||||
@ -19,6 +20,7 @@ import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.core.*
|
||||
import ru.dbotthepony.mc.otm.core.math.BlockRotation
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
||||
import ru.dbotthepony.mc.otm.core.nbt.getByteArrayList
|
||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||
@ -84,14 +86,14 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
return value
|
||||
}
|
||||
|
||||
override fun saveShared(nbt: CompoundTag) {
|
||||
super.saveShared(nbt)
|
||||
override fun saveShared(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveShared(nbt, registry)
|
||||
nbt[PASSED_ENERGY_KEY] = passed.serializeNBT()
|
||||
ioLimit?.let { nbt[IO_LIMIT_KEY] = it.serializeNBT() }
|
||||
}
|
||||
|
||||
override fun saveLevel(nbt: CompoundTag) {
|
||||
super.saveLevel(nbt)
|
||||
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.saveLevel(nbt, registry)
|
||||
val list = ListTag()
|
||||
nbt[POWER_HISTORY_KEY] = list
|
||||
nbt[POWER_HISTORY_POINTER_KEY] = historyTick
|
||||
@ -100,8 +102,8 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
list.add(num.serializeNBT())
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
|
||||
passed = nbt.getDecimal(PASSED_ENERGY_KEY)
|
||||
ioLimit = nbt.mapPresent(IO_LIMIT_KEY, Decimal.Companion::deserializeNBT)
|
||||
@ -127,8 +129,8 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
private val energyInput = EnergyCounterCap(true)
|
||||
private val energyOutput = EnergyCounterCap(false)
|
||||
|
||||
private val inputCapability by front.trackEnergy()
|
||||
private val outputCapability by back.trackEnergy()
|
||||
private val inputCapability by CapabilityCache(RelativeSide.FRONT, Capabilities.EnergyStorage.BLOCK)
|
||||
private val outputCapability by CapabilityCache(RelativeSide.BACK, Capabilities.EnergyStorage.BLOCK)
|
||||
|
||||
private inner class EnergyCounterCap(isInput: Boolean) : IMatteryEnergyStorage {
|
||||
override val energyFlow = FlowDirection.input(isInput)
|
||||
@ -137,7 +139,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
if (redstoneControl.isBlockedByRedstone)
|
||||
return Decimal.ZERO
|
||||
|
||||
val it = inputCapability.orNull()
|
||||
val it = inputCapability
|
||||
|
||||
if (it != null) {
|
||||
val diff: Decimal
|
||||
@ -165,7 +167,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
if (redstoneControl.isBlockedByRedstone)
|
||||
return Decimal.ZERO
|
||||
|
||||
val it = outputCapability.orNull()
|
||||
val it = outputCapability
|
||||
|
||||
if (it != null) {
|
||||
val diff: Decimal
|
||||
@ -195,7 +197,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
override var batteryLevel: Decimal
|
||||
get() {
|
||||
if (energyFlow.input) {
|
||||
val it = outputCapability.orNull()
|
||||
val it = outputCapability
|
||||
|
||||
if (it != null) {
|
||||
if (it is IMatteryEnergyStorage) {
|
||||
@ -205,7 +207,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
return Decimal(it.energyStored)
|
||||
}
|
||||
} else {
|
||||
val it = inputCapability.orNull()
|
||||
val it = inputCapability
|
||||
|
||||
if (it != null) {
|
||||
if (it is IMatteryEnergyStorage) {
|
||||
@ -225,7 +227,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
override val maxBatteryLevel: Decimal
|
||||
get() {
|
||||
if (energyFlow.input) {
|
||||
val it = outputCapability.orNull()
|
||||
val it = outputCapability
|
||||
|
||||
if (it != null) {
|
||||
if (it is IMatteryEnergyStorage) {
|
||||
@ -235,7 +237,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
return Decimal(it.maxEnergyStored)
|
||||
}
|
||||
} else {
|
||||
val it = inputCapability.orNull()
|
||||
val it = inputCapability
|
||||
|
||||
if (it != null) {
|
||||
if (it is IMatteryEnergyStorage) {
|
||||
@ -252,7 +254,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
override val missingPower: Decimal
|
||||
get() {
|
||||
if (energyFlow.input) {
|
||||
val it = outputCapability.orNull()
|
||||
val it = outputCapability
|
||||
|
||||
if (it != null) {
|
||||
if (it is IMatteryEnergyStorage) {
|
||||
@ -262,7 +264,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
return Decimal((it.maxEnergyStored - it.energyStored).coerceAtLeast(0))
|
||||
}
|
||||
} else {
|
||||
val it = inputCapability.orNull()
|
||||
val it = inputCapability
|
||||
|
||||
if (it != null) {
|
||||
if (it is IMatteryEnergyStorage) {
|
||||
@ -278,11 +280,8 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
||||
}
|
||||
|
||||
init {
|
||||
front.Cap(ForgeCapabilities.ENERGY, energyInput)
|
||||
front.Cap(MatteryCapability.ENERGY, energyInput)
|
||||
|
||||
back.Cap(ForgeCapabilities.ENERGY, energyOutput)
|
||||
back.Cap(MatteryCapability.ENERGY, energyOutput)
|
||||
exposeEnergySided(RelativeSide.FRONT, energyInput)
|
||||
exposeEnergySided(RelativeSide.BACK, energyOutput)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
|
@ -7,10 +7,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
|
||||
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.moveEnergy
|
||||
@ -19,7 +18,6 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.MultiblockBuilder
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.menu.tech.EnergyHatchMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
|
||||
@ -32,7 +30,7 @@ class EnergyHatchBlockEntity(
|
||||
) : MatteryDeviceBlockEntity(type, blockPos, blockState) {
|
||||
val energy = ProfiledEnergyStorage(BlockEnergyStorageImpl(this::markDirtyFast, FlowDirection.input(isInput), capacity))
|
||||
|
||||
val container = object : MatteryContainer(this::markDirtyFast, CAPACITY) {
|
||||
val container = object : MatteryContainer(::markDirtyFast, CAPACITY) {
|
||||
override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int {
|
||||
return 1
|
||||
}
|
||||
@ -45,9 +43,8 @@ class EnergyHatchBlockEntity(
|
||||
savetables.stateful(::container, BATTERY_KEY)
|
||||
|
||||
// it would cause a lot of frustration if hatches accept stuff only though one face
|
||||
exposeGlobally(ForgeCapabilities.ENERGY, energy)
|
||||
exposeGlobally(MatteryCapability.ENERGY, energy)
|
||||
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler)
|
||||
exposeGlobally(Capabilities.EnergyStorage.BLOCK, energy)
|
||||
exposeGlobally(Capabilities.ItemHandler.BLOCK, itemHandler)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
@ -55,7 +52,7 @@ class EnergyHatchBlockEntity(
|
||||
|
||||
if (!redstoneControl.isBlockedByRedstone) {
|
||||
container.forEach {
|
||||
it.getCapability(ForgeCapabilities.ENERGY).ifPresentK {
|
||||
it.getCapability(Capabilities.EnergyStorage.ITEM)?.let {
|
||||
if (isInput) {
|
||||
moveEnergy(it, energy, simulate = false)
|
||||
} else {
|
||||
|
@ -1,6 +1,9 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.tech
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
@ -9,11 +12,12 @@ import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.enchantment.Enchantment
|
||||
import net.minecraft.world.item.enchantment.Enchantments
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.neoforged.neoforge.fluids.FluidStack
|
||||
import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
||||
import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage.Companion.XP_TO_LIQUID_RATIO
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock
|
||||
@ -22,6 +26,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
|
||||
import ru.dbotthepony.mc.otm.core.lookupOrThrow
|
||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||
import ru.dbotthepony.mc.otm.core.util.countingLazy
|
||||
import ru.dbotthepony.mc.otm.item.EssenceCapsuleItem
|
||||
@ -42,6 +47,8 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
||||
val servoContainer = MatteryContainer(::markDirtyFast, 1)
|
||||
val mendingContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)
|
||||
|
||||
private var mending: Holder<Enchantment>? = null
|
||||
|
||||
init {
|
||||
savetables.long(::experienceStored)
|
||||
savetables.stateful(::capsuleContainer)
|
||||
@ -62,7 +69,7 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
||||
})),
|
||||
mendingContainer.handler(object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
return stack.isDamaged && stack.getEnchantmentLevel(Enchantments.MENDING) > 0
|
||||
return stack.isDamaged && stack.getEnchantmentLevel(mending!!) > 0
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
|
||||
@ -72,6 +79,12 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
||||
)
|
||||
)
|
||||
|
||||
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
super.loadAdditional(nbt, registry)
|
||||
|
||||
mending = registry.lookupOrThrow(Enchantments.MENDING)
|
||||
}
|
||||
|
||||
val fluidConfig = ConfigurableFluidHandler(this)
|
||||
|
||||
override fun getTanks(): Int {
|
||||
|
@ -70,10 +70,6 @@ class GravitationStabilizerBlockEntity(p_155229_: BlockPos, p_155230_: BlockStat
|
||||
blackHole?.stabilizerDetached(this)
|
||||
}
|
||||
|
||||
override fun getRenderBoundingBox(): AABB {
|
||||
return AABB(blockPos.offset(-RANGE, -RANGE, -RANGE), blockPos.offset(RANGE, RANGE, RANGE))
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val RANGE = 64
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
@ -26,7 +26,7 @@ class ItemHatchBlockEntity(
|
||||
|
||||
init {
|
||||
savetables.stateful(::container, INVENTORY_KEY)
|
||||
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler)
|
||||
exposeGlobally(Capabilities.ItemHandler.BLOCK, itemHandler)
|
||||
}
|
||||
|
||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||
|
@ -7,7 +7,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
@ -18,7 +18,6 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.MultiblockBuilder
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.menu.tech.MatterHatchMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
@ -29,7 +28,7 @@ class MatterHatchBlockEntity(
|
||||
blockPos: BlockPos,
|
||||
blockState: BlockState
|
||||
) : MatteryDeviceBlockEntity(type, blockPos, blockState) {
|
||||
val container = object : MatteryContainer(this::markDirtyFast, CAPACITY) {
|
||||
val container = object : MatteryContainer(::markDirtyFast, CAPACITY) {
|
||||
override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int {
|
||||
return 1
|
||||
}
|
||||
@ -48,8 +47,8 @@ class MatterHatchBlockEntity(
|
||||
savetables.stateful(::matter, MATTER_STORAGE_KEY)
|
||||
|
||||
// it would cause a lot of frustration if hatches accept stuff only though one face
|
||||
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler)
|
||||
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||
exposeGlobally(Capabilities.ItemHandler.BLOCK, itemHandler)
|
||||
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
@ -57,7 +56,7 @@ class MatterHatchBlockEntity(
|
||||
|
||||
if (!redstoneControl.isBlockedByRedstone && matter.missingMatter > Decimal.ZERO) {
|
||||
container.forEach {
|
||||
it.getCapability(MatteryCapability.MATTER).ifPresentK {
|
||||
it.getCapability(MatteryCapability.MATTER_ITEM)?.let {
|
||||
if (isInput) {
|
||||
moveMatter(it, matter, simulate = false)
|
||||
} else {
|
||||
|
@ -6,7 +6,7 @@ import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage
|
||||
import ru.dbotthepony.mc.otm.block.entity.JobContainer
|
||||
import ru.dbotthepony.mc.otm.block.entity.JobStatus
|
||||
@ -44,7 +44,7 @@ class PlatePressBlockEntity(
|
||||
)
|
||||
|
||||
init {
|
||||
exposeGlobally(ForgeCapabilities.FLUID_HANDLER, experience)
|
||||
exposeGlobally(Capabilities.FluidHandler.BLOCK, experience)
|
||||
|
||||
savetables.stateful(::energy, ENERGY_KEY)
|
||||
savetables.stateful(::inputContainer)
|
||||
@ -76,7 +76,6 @@ class PlatePressBlockEntity(
|
||||
|
||||
val recipe = level.recipeManager
|
||||
.byType(MRecipes.PLATE_PRESS)
|
||||
.values
|
||||
.iterator()
|
||||
.filter { it.value.matches(inputContainer, id) }
|
||||
.maybe()?.value ?: return JobContainer.noItem()
|
||||
|
@ -22,7 +22,7 @@ import ru.dbotthepony.mc.otm.block.addSimpleDescription
|
||||
import ru.dbotthepony.mc.otm.block.entity.tech.AndroidStationBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.WorkerState
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.shapes.BlockShapes
|
||||
|
||||
@ -41,9 +41,7 @@ class AndroidStationBlock(val color: DyeColor?) : MatteryBlock(DEFAULT_MACHINE_P
|
||||
hand: InteractionHand,
|
||||
blockHitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
val cap = ply.getCapability(MatteryCapability.MATTERY_PLAYER).orNull() ?: return InteractionResult.FAIL
|
||||
|
||||
if (!cap.isAndroid)
|
||||
if (!ply.matteryPlayer.isAndroid)
|
||||
return InteractionResult.FAIL
|
||||
|
||||
return super.use(blockState, level, blockPos, ply, hand, blockHitResult)
|
||||
|
@ -40,7 +40,7 @@ class EssenceStorageBlock(val color: DyeColor?) : RotatableMatteryBlock(Properti
|
||||
|
||||
addSimpleDescription()
|
||||
|
||||
tooltips.blockEntityData<LongTag>("experienceStored") { _, l, acceptor ->
|
||||
tooltips.blockEntityData<LongTag>("experienceStored") { _, _, l, acceptor ->
|
||||
if (minecraft.window.isShiftDown) {
|
||||
acceptor(TranslatableComponent("otm.gui.experience", l.asLong).withStyle(ChatFormatting.GRAY))
|
||||
} else {
|
||||
|
@ -2,10 +2,11 @@ package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.NumericTag
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable
|
||||
import ru.dbotthepony.mc.otm.core.forValidRefs
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||
@ -81,7 +82,7 @@ abstract class AbstractProfiledStorage<out P>(val parent: P) : INBTSerializable<
|
||||
}
|
||||
|
||||
val savedata: INBTSerializable<CompoundTag?> = object : INBTSerializable<CompoundTag?> {
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
return CompoundTag().also { tag ->
|
||||
tag["historyReceive"] = ListTag().also {
|
||||
for (value in historyReceiveInternal) {
|
||||
@ -99,7 +100,7 @@ abstract class AbstractProfiledStorage<out P>(val parent: P) : INBTSerializable<
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag?) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag?) {
|
||||
tick = 0
|
||||
thisTickReceive = Decimal.ZERO
|
||||
thisTickTransfer = Decimal.ZERO
|
||||
@ -131,16 +132,16 @@ abstract class AbstractProfiledStorage<out P>(val parent: P) : INBTSerializable<
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
val tag: CompoundTag
|
||||
|
||||
if (parent is INBTSerializable<*>) {
|
||||
tag = (parent as INBTSerializable<CompoundTag?>).serializeNBT() ?: CompoundTag()
|
||||
tag = (parent as INBTSerializable<CompoundTag?>).serializeNBT(registry) ?: CompoundTag()
|
||||
} else {
|
||||
tag = CompoundTag()
|
||||
}
|
||||
|
||||
val tag2 = savedata.serializeNBT()!!
|
||||
val tag2 = savedata.serializeNBT(registry)!!
|
||||
|
||||
for (k in tag2.allKeys) {
|
||||
tag[k] = tag2[k]!!
|
||||
@ -157,12 +158,12 @@ abstract class AbstractProfiledStorage<out P>(val parent: P) : INBTSerializable<
|
||||
return calcWeightedAverage(historyReceive, tick)
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag?) {
|
||||
override fun deserializeNBT(registry: HolderLookup.Provider, nbt: CompoundTag?) {
|
||||
if (parent is INBTSerializable<*>) {
|
||||
(parent as INBTSerializable<CompoundTag?>).deserializeNBT(nbt)
|
||||
(parent as INBTSerializable<CompoundTag?>).deserializeNBT(registry, nbt)
|
||||
}
|
||||
|
||||
savedata.deserializeNBT(nbt)
|
||||
savedata.deserializeNBT(registry, nbt)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -3,14 +3,14 @@ package ru.dbotthepony.mc.otm.capability
|
||||
import com.google.common.collect.Streams
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider
|
||||
import net.minecraftforge.energy.IEnergyStorage
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage
|
||||
import net.neoforged.neoforge.fluids.FluidStack
|
||||
import net.neoforged.neoforge.fluids.capability.IFluidHandler
|
||||
import net.neoforged.neoforge.items.IItemHandler
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.fluid.iterator
|
||||
@ -33,13 +33,13 @@ import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
|
||||
import java.util.stream.Stream
|
||||
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
|
||||
val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull()
|
||||
val Player.matteryPlayer: MatteryPlayer get() = (this as IMatteryPlayer).otmPlayer
|
||||
val LivingEntity.matteryPlayer: MatteryPlayer? get() = (this as? IMatteryPlayer)?.otmPlayer
|
||||
|
||||
/**
|
||||
* Does a checked energy receive, calls [IMatteryEnergyStorage.receiveEnergyChecked] if possible
|
||||
@ -131,21 +131,21 @@ val IEnergyStorage.chargeRatio: Float get() {
|
||||
/**
|
||||
* Shortcut for getting [IEnergyStorage], including wrappers for it
|
||||
*/
|
||||
val ICapabilityProvider.energy: IEnergyStorage? get() {
|
||||
val mattery = getCapability(MatteryCapability.ENERGY)
|
||||
val ItemStack.energy: IEnergyStorage? get() {
|
||||
//val mattery = getCapability(MatteryCapability.ITEM_ENERGY)
|
||||
|
||||
if (mattery.isPresent) {
|
||||
return mattery.orNull()
|
||||
}
|
||||
//if (mattery != null) {
|
||||
// return mattery
|
||||
//}
|
||||
|
||||
return getCapability(ForgeCapabilities.ENERGY).orNull()
|
||||
return getCapability(Capabilities.EnergyStorage.ITEM)
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for getting sideless [IMatteryEnergyStorage], including wrappers for it
|
||||
*/
|
||||
val ICapabilityProvider.matteryEnergy: IMatteryEnergyStorage? get() {
|
||||
return getCapability(MatteryCapability.ENERGY).orNull()
|
||||
val ItemStack.matteryEnergy: IMatteryEnergyStorage? get() {
|
||||
return getCapability(MatteryCapability.ITEM_ENERGY)
|
||||
}
|
||||
|
||||
fun Player.items(includeCosmetics: Boolean = true): Iterator<ItemStack> {
|
||||
@ -320,7 +320,7 @@ internal fun IFluidHandler.fluidLevel(tooltips: (Component) -> Unit) {
|
||||
if (fluid.isEmpty) {
|
||||
tooltips(formatFluidLevel(0, getTankCapacity(0), formatAsReadable = ShiftPressedCond).withStyle(ChatFormatting.GRAY))
|
||||
} else {
|
||||
tooltips(formatFluidLevel(fluid.amount, getTankCapacity(0), fluid.displayName, formatAsReadable = ShiftPressedCond).withStyle(ChatFormatting.GRAY))
|
||||
tooltips(formatFluidLevel(fluid.amount, getTankCapacity(0), fluid.hoverName, formatAsReadable = ShiftPressedCond).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,18 +330,18 @@ private fun actuallyMoveFluid(drained: FluidStack, source: IFluidHandler, destin
|
||||
val filled = destination.fill(drained, IFluidHandler.FluidAction.SIMULATE)
|
||||
if (filled == 0) return FluidStack.EMPTY
|
||||
|
||||
val drained2 = source.drain(FluidStack(drained, filled), IFluidHandler.FluidAction.SIMULATE)
|
||||
val drained2 = source.drain(drained.copyWithAmount(filled), IFluidHandler.FluidAction.SIMULATE)
|
||||
if (drained2.amount != filled) return FluidStack.EMPTY
|
||||
|
||||
val filled2 = destination.fill(drained2, IFluidHandler.FluidAction.SIMULATE)
|
||||
if (filled2 != drained2.amount) return FluidStack.EMPTY
|
||||
|
||||
if (!actuallyDrain && !actuallyFill) return FluidStack(drained2, filled2)
|
||||
if (!actuallyDrain && !actuallyFill) return drained2.copyWithAmount(filled2)
|
||||
|
||||
val drained3: FluidStack
|
||||
|
||||
if (actuallyDrain) {
|
||||
drained3 = source.drain(FluidStack(drained2, filled2), IFluidHandler.FluidAction.EXECUTE)
|
||||
drained3 = source.drain(drained2.copyWithAmount(filled2), IFluidHandler.FluidAction.EXECUTE)
|
||||
|
||||
if (drained3.amount != filled2) {
|
||||
LOGGER.warn("Inconsistency of fluid extraction from $source between simulate and execute modes (simulated $drained2; extracted $drained3); This can lead to duping!!!")
|
||||
@ -362,7 +362,7 @@ private fun actuallyMoveFluid(drained: FluidStack, source: IFluidHandler, destin
|
||||
filled3 = filled2
|
||||
}
|
||||
|
||||
return FluidStack(drained3, filled3)
|
||||
return drained3.copyWithAmount(filled3)
|
||||
}
|
||||
|
||||
fun moveFluid(source: IFluidHandler, sourceTank: Int? = null, destination: IFluidHandler, limit: Int = Int.MAX_VALUE, actuallyDrain: Boolean = true, actuallyFill: Boolean = true): FluidStack {
|
||||
|
@ -0,0 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
interface IMatteryPlayer {
|
||||
// since new capabilities dont get to live through getCapability calls by design
|
||||
// and data attachments are.... limited.
|
||||
// We gonna do it Fabric way
|
||||
val otmPlayer: MatteryPlayer
|
||||
}
|
@ -10,12 +10,14 @@ import net.minecraft.client.model.PlayerModel
|
||||
import net.minecraft.client.player.AbstractClientPlayer
|
||||
import net.minecraft.commands.Commands
|
||||
import net.minecraft.commands.arguments.EntityArgument
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.IntTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@ -26,40 +28,31 @@ import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.boss.wither.WitherBoss
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.ProjectileWeaponItem
|
||||
import net.minecraft.world.item.crafting.RecipeManager
|
||||
import net.minecraft.world.item.crafting.RecipeType
|
||||
import net.minecraft.world.item.crafting.SingleRecipeInput
|
||||
import net.minecraft.world.level.GameRules
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.common.ForgeHooks
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.common.capabilities.Capability
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.minecraftforge.common.util.LazyOptional
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent
|
||||
import net.minecraftforge.event.RegisterCommandsEvent
|
||||
import net.minecraftforge.event.TickEvent
|
||||
import net.minecraftforge.event.TickEvent.PlayerTickEvent
|
||||
import net.minecraftforge.event.entity.living.LivingAttackEvent
|
||||
import net.minecraftforge.event.entity.living.LivingDeathEvent
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||
import net.minecraftforge.event.entity.living.MobEffectEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent
|
||||
import net.minecraftforge.eventbus.api.Cancelable
|
||||
import net.minecraftforge.eventbus.api.Event
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.server.command.EnumArgument
|
||||
import net.neoforged.bus.api.Event
|
||||
import net.neoforged.bus.api.ICancellableEvent
|
||||
import net.neoforged.neoforge.common.CommonHooks
|
||||
import net.neoforged.neoforge.common.NeoForge
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent
|
||||
import net.neoforged.neoforge.event.entity.living.LivingDeathEvent
|
||||
import net.neoforged.neoforge.event.entity.living.LivingIncomingDamageEvent
|
||||
import net.neoforged.neoforge.event.entity.living.MobEffectEvent
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerEvent
|
||||
import net.neoforged.neoforge.event.tick.PlayerTickEvent
|
||||
import net.neoforged.neoforge.network.PacketDistributor
|
||||
import net.neoforged.neoforge.server.command.EnumArgument
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.joml.Vector4f
|
||||
import ru.dbotthepony.kommons.collect.ListenableMap
|
||||
@ -93,18 +86,18 @@ import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||
import ru.dbotthepony.mc.otm.config.ExopackConfig
|
||||
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.container.DynamicallyProxiedContainer
|
||||
import ru.dbotthepony.mc.otm.container.IContainer
|
||||
import ru.dbotthepony.mc.otm.container.IMatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.container.util.slotIterator
|
||||
import ru.dbotthepony.mc.otm.container.vanishCursedItems
|
||||
import ru.dbotthepony.mc.otm.core.*
|
||||
import ru.dbotthepony.mc.otm.core.collect.UUIDIntModifiersMap
|
||||
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.math.RGBColorDFUCodec
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.RGBColorDFUCodec
|
||||
import ru.dbotthepony.mc.otm.core.math.minus
|
||||
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
||||
import ru.dbotthepony.mc.otm.core.nbt.getIntList
|
||||
@ -147,45 +140,32 @@ private fun Player.dropContainer(container: Container, spill: Boolean = true, se
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerializable<CompoundTag> {
|
||||
class MatteryPlayer(val ply: Player) {
|
||||
/**
|
||||
* This event is fired on main event bus before ticking logic takes place.
|
||||
*
|
||||
* Cancelling it is probably not a good idea, but you can do it anyway.
|
||||
*/
|
||||
@Cancelable
|
||||
data class PreTick(val capability: MatteryPlayerCapability) : Event() {
|
||||
data class PreTick(val capability: MatteryPlayer) : Event(), ICancellableEvent {
|
||||
val player get() = capability.ply
|
||||
val level: Level get() = capability.ply.level()
|
||||
|
||||
override fun isCancelable(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired on main event bus after ticking logic took place.
|
||||
*/
|
||||
data class PostTick(val capability: MatteryPlayerCapability) : Event() {
|
||||
data class PostTick(val capability: MatteryPlayer) : Event() {
|
||||
val player get() = capability.ply
|
||||
val level: Level get() = capability.ply.level()
|
||||
|
||||
override fun isCancelable(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired on main event bus when [Inventory.add] was called and entire [ItemStack] can not be stored
|
||||
* (both in [Inventory] and [MatteryPlayerCapability] exopack due to inventory filters or no free space).
|
||||
* (both in [Inventory] and [MatteryPlayer] exopack due to inventory filters or no free space).
|
||||
*/
|
||||
data class ItemStackLeftoverEvent(val stack: ItemStack, val capability: MatteryPlayerCapability) : Event() {
|
||||
data class ItemStackLeftoverEvent(val stack: ItemStack, val capability: MatteryPlayer) : Event() {
|
||||
val player get() = capability.ply
|
||||
val level: Level get() = capability.ply.level()
|
||||
|
||||
override fun isCancelable(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private inner class PlayerMatteryContainer(size: Int) : MatteryContainer(size) {
|
||||
@ -327,7 +307,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
field[i] = ItemStack.EMPTY
|
||||
}
|
||||
|
||||
value.deserializeNBT(field.serializeNBT())
|
||||
value.deserializeNBT(ply.level().registryAccess(), field.serializeNBT(ply.level().registryAccess()))
|
||||
value.addFilterSynchronizer(syncher)
|
||||
field = value
|
||||
|
||||
@ -449,7 +429,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
private val deathLog = ArrayDeque<Pair<Int, Component>>()
|
||||
|
||||
private val featureMap = IdentityHashMap<AndroidFeatureType<*>, AndroidFeature>()
|
||||
private val networkQueue = ArrayList<Any>()
|
||||
private val networkQueue = ArrayList<CustomPacketPayload>()
|
||||
private val queuedTicks = ArrayList<Runnable>()
|
||||
private var tickedOnce = false
|
||||
|
||||
@ -474,7 +454,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
private var lastLiquidPosition = Vec3(0.0, 0.0, 0.0)
|
||||
private var liquidDistanceTravelled = 0.0
|
||||
private var wasInLiquid = false
|
||||
private var lastDimension = ResourceLocation("overworld")
|
||||
private var lastDimension = ResourceLocation("minecraft", "overworld")
|
||||
|
||||
// clientside only flag for render hook
|
||||
// TODO: actual code, currently particles spawn just behind player on ExopackSmokePacket
|
||||
@ -539,13 +519,13 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
override fun computeNextJob(): JobContainer<ItemJob> {
|
||||
if (!exopackEnergy.batteryLevel.isPositive) return JobContainer.noEnergy()
|
||||
val level = ply.level() as? ServerLevel ?: return JobContainer.failure()
|
||||
val recipe = cache.getRecipeFor(input, level)
|
||||
val recipe = cache.getRecipeFor(SingleRecipeInput(input[0]), level)
|
||||
|
||||
if (recipe.isEmpty) {
|
||||
return JobContainer.noItem()
|
||||
} else {
|
||||
val actual = recipe.get()
|
||||
val item = actual.value.assemble(input, level.registryAccess())
|
||||
val item = actual.value.assemble(SingleRecipeInput(input[0]), level.registryAccess())
|
||||
input[0].shrink(1)
|
||||
input.setChanged(0)
|
||||
return JobContainer.success(ItemJob(item, actual.value.cookingTime.toDouble(), ExopackConfig.FURNACE_POWER_CONSUMPTION, actual.value.experience))
|
||||
@ -556,7 +536,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
super.onJobTick(status)
|
||||
|
||||
if (isExopackVisible && ply.level().random.nextFloat() <= 0.05f) {
|
||||
MatteryPlayerNetworkChannel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(ply as ServerPlayer), ExopackSmokePacket(ply.uuid))
|
||||
PacketDistributor.sendToPlayersTrackingEntityAndSelf(ply, ExopackSmokePacket(ply.uuid))
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,7 +892,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
return featureMap[feature] as T?
|
||||
}
|
||||
|
||||
private fun onHurt(event: LivingHurtEvent) {
|
||||
private fun onHurt(event: LivingIncomingDamageEvent) {
|
||||
if (isAndroid) {
|
||||
for (feature in featureMap.values) {
|
||||
feature.onHurt(event)
|
||||
@ -924,14 +904,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
}
|
||||
|
||||
private fun onAttack(event: LivingAttackEvent) {
|
||||
if (isAndroid) {
|
||||
for (feature in featureMap.values) {
|
||||
feature.onAttack(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T : AndroidFeature> computeIfAbsent(feature: AndroidFeatureType<T>): T {
|
||||
return getFeature(feature) ?: addFeature(feature)
|
||||
}
|
||||
@ -947,22 +919,22 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
val tag = savetables.serializeNBT()
|
||||
fun serializeNBT(registry: HolderLookup.Provider): CompoundTag {
|
||||
val tag = savetables.serializeNBT(registry)
|
||||
|
||||
// iteration
|
||||
tag["deathLog"] = ListTag().also {
|
||||
for ((ticks, component) in deathLog) {
|
||||
it.add(CompoundTag().also {
|
||||
it["ticks"] = ticks
|
||||
it["component"] = StringTag.valueOf(Component.Serializer.toJson(component))
|
||||
it["component"] = StringTag.valueOf(Component.Serializer.toJson(component, registry))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
tag["features"] = ListTag().also {
|
||||
for (feature in featureMap.values) {
|
||||
it.add(feature.serializeNBT().also {
|
||||
it.add(feature.serializeNBT(registry).also {
|
||||
it["id"] = feature.type.registryName!!.toString()
|
||||
})
|
||||
}
|
||||
@ -991,8 +963,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
return tag
|
||||
}
|
||||
|
||||
override fun deserializeNBT(tag: CompoundTag) {
|
||||
savetables.deserializeNBT(tag)
|
||||
fun deserializeNBT(tag: CompoundTag, registry: HolderLookup.Provider) {
|
||||
savetables.deserializeNBT(registry, tag)
|
||||
|
||||
if (MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON.uuid(ItemStack.EMPTY) in exopackSlotModifierMap.delegate) {
|
||||
isExopackEnderAccessInstalled = true
|
||||
@ -1014,7 +986,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
for (i in 0 until regularSlotFilters.size.coerceAtMost(this.regularSlotFilters.size)) {
|
||||
val path = regularSlotFilters[i].asString
|
||||
if (path == "") continue
|
||||
this.regularSlotFilters[i].value = ForgeRegistries.ITEMS.getValue(ResourceLocation.tryParse(path) ?: continue) ?: Items.AIR
|
||||
this.regularSlotFilters[i].value = BuiltInRegistries.ITEM.get(ResourceLocation.tryParse(path) ?: continue)
|
||||
}
|
||||
|
||||
if ("slotsChargeFlag" in tag) {
|
||||
@ -1029,7 +1001,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
deathLog.clear()
|
||||
|
||||
for (value in tag.getCompoundList("deathLog")) {
|
||||
val component = Component.Serializer.fromJson(value.getString("component"))
|
||||
val component = Component.Serializer.fromJson(value.getString("component"), registry)
|
||||
|
||||
if (component != null) {
|
||||
deathLog.add(value.getInt("ticks") to component)
|
||||
@ -1040,12 +1012,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
research.clear()
|
||||
|
||||
for (featureTag in tag.getCompoundList("features")) {
|
||||
val feature = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(featureTag.getString("id")))
|
||||
val feature = MRegistry.ANDROID_FEATURES.get(ResourceLocation.parse(featureTag.getString("id")))
|
||||
|
||||
if (feature?.isApplicable(this) == true) {
|
||||
val instance = feature.create(this)
|
||||
|
||||
instance.deserializeNBT(featureTag)
|
||||
instance.deserializeNBT(registry, featureTag)
|
||||
addFeature(instance)
|
||||
|
||||
if (!ply.level().isClientSide) {
|
||||
@ -1055,7 +1027,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
|
||||
for (researchTag in tag.getCompoundList("research")) {
|
||||
val research = AndroidResearchManager[ResourceLocation(researchTag.getString("id"))]
|
||||
val research = AndroidResearchManager[ResourceLocation.parse(researchTag.getString("id"))]
|
||||
|
||||
if (research != null) {
|
||||
val instance = AndroidResearch(research, this)
|
||||
@ -1088,10 +1060,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
androidEnergy.item = ItemStack.EMPTY
|
||||
}
|
||||
|
||||
private fun sendNetwork(packet: Any) {
|
||||
private fun sendNetwork(packet: CustomPacketPayload) {
|
||||
if (ply is ServerPlayer) {
|
||||
if (tickedOnce) {
|
||||
MatteryPlayerNetworkChannel.send(ply, packet)
|
||||
PacketDistributor.sendToPlayer(ply, packet)
|
||||
} else {
|
||||
networkQueue.add(packet)
|
||||
}
|
||||
@ -1128,7 +1100,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
if (!ply.isAlive) return
|
||||
|
||||
if (isAndroid) {
|
||||
ForgeRegistries.MOB_EFFECTS.tags()?.getTag(ANDROID_IMMUNE_EFFECTS)?.forEach {
|
||||
BuiltInRegistries.MOB_EFFECT.getOrCreateTag(ANDROID_IMMUNE_EFFECTS).forEach {
|
||||
if (ply.hasEffect(it))
|
||||
ply.removeEffect(it)
|
||||
}
|
||||
@ -1138,10 +1110,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
private fun tick() {
|
||||
if (!ply.isAlive) return
|
||||
|
||||
PreTick(this).also {
|
||||
MinecraftForge.EVENT_BUS.post(it)
|
||||
if (it.isCanceled) return
|
||||
}
|
||||
if (NeoForge.EVENT_BUS.post(PreTick(this)).isCanceled) return
|
||||
|
||||
ticksIExist++
|
||||
|
||||
@ -1335,7 +1304,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
val payload = privateSyncherRemote.write()
|
||||
|
||||
if (payload != null) {
|
||||
MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload, false))
|
||||
PacketDistributor.sendToPlayer(ply as ServerPlayer, MatteryPlayerDataPacket(payload, false))
|
||||
}
|
||||
|
||||
val trackingIterator = remoteSynchers.entries.iterator()
|
||||
@ -1349,19 +1318,19 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
val payload2 = remote.write()
|
||||
|
||||
if (payload2 != null) {
|
||||
MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload2, true, this.ply.uuid))
|
||||
PacketDistributor.sendToPlayer(ply as ServerPlayer, MatteryPlayerDataPacket(payload2, true, this.ply.uuid))
|
||||
}
|
||||
}
|
||||
|
||||
val payload3 = publicSyncherRemote.write()
|
||||
|
||||
if (payload3 != null) {
|
||||
MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload3, true))
|
||||
PacketDistributor.sendToPlayer(ply as ServerPlayer, MatteryPlayerDataPacket(payload3, true))
|
||||
}
|
||||
|
||||
if (networkQueue.size != 0) {
|
||||
for (packet in networkQueue) {
|
||||
MatteryPlayerNetworkChannel.send(ply, packet)
|
||||
PacketDistributor.sendToPlayer(ply as ServerPlayer, packet)
|
||||
}
|
||||
|
||||
networkQueue.clear()
|
||||
@ -1395,18 +1364,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
tickInventory()
|
||||
|
||||
PostTick(this).also {
|
||||
MinecraftForge.EVENT_BUS.post(it)
|
||||
NeoForge.EVENT_BUS.post(it)
|
||||
}
|
||||
}
|
||||
|
||||
private val resolver = LazyOptional.of { this }
|
||||
|
||||
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
return if (cap == MatteryCapability.MATTERY_PLAYER) {
|
||||
resolver.cast()
|
||||
} else LazyOptional.empty()
|
||||
}
|
||||
|
||||
/**
|
||||
* This re-implement [Inventory.add] logic (original method is redirected to this)
|
||||
*/
|
||||
@ -1421,7 +1382,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
wrappedItemInventory.consumeItem(stack, false, onlyIntoExisting = false, popTime = 5)
|
||||
}
|
||||
|
||||
MinecraftForge.EVENT_BUS.post(ItemStackLeftoverEvent(stack, this))
|
||||
NeoForge.EVENT_BUS.post(ItemStackLeftoverEvent(stack, this))
|
||||
|
||||
if (ply.abilities.instabuild) {
|
||||
stack.count = 0
|
||||
@ -1445,10 +1406,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
}
|
||||
|
||||
enum class UpgradeType(val prop: KMutableProperty1<MatteryPlayerCapability, Boolean>) {
|
||||
CRAFTING(MatteryPlayerCapability::isExopackCraftingUpgraded),
|
||||
ENDER_ACCESS(MatteryPlayerCapability::isExopackEnderAccessInstalled),
|
||||
SMELTING(MatteryPlayerCapability::isExopackSmeltingInstalled);
|
||||
enum class UpgradeType(val prop: KMutableProperty1<MatteryPlayer, Boolean>) {
|
||||
CRAFTING(MatteryPlayer::isExopackCraftingUpgraded),
|
||||
ENDER_ACCESS(MatteryPlayer::isExopackEnderAccessInstalled),
|
||||
SMELTING(MatteryPlayer::isExopackSmeltingInstalled);
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@ -1457,8 +1418,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
private fun setExoPack(players: Collection<Player>, hasExoPack: Boolean): Int {
|
||||
for (player in players) {
|
||||
player.matteryPlayer?.hasExopack = hasExoPack
|
||||
player.matteryPlayer?._exoPackMenu = null
|
||||
player.matteryPlayer.hasExopack = hasExoPack
|
||||
player.matteryPlayer._exoPackMenu = null
|
||||
}
|
||||
|
||||
return players.size
|
||||
@ -1466,7 +1427,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
private fun makeAndroid(players: Collection<Player>): Int {
|
||||
for (player in players) {
|
||||
player.matteryPlayer?.becomeAndroid()
|
||||
player.matteryPlayer.becomeAndroid()
|
||||
}
|
||||
|
||||
return players.size
|
||||
@ -1474,7 +1435,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
private fun makeHuman(players: Collection<Player>): Int {
|
||||
for (player in players) {
|
||||
player.matteryPlayer?.becomeHumane()
|
||||
player.matteryPlayer.becomeHumane()
|
||||
}
|
||||
|
||||
return players.size
|
||||
@ -1482,7 +1443,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
private fun setUpgrade(players: Collection<Player>, type: UpgradeType, state: Boolean): Int {
|
||||
for (player in players) {
|
||||
player.matteryPlayer?.let { type.prop.set(it, state) }
|
||||
player.matteryPlayer.let { type.prop.set(it, state) }
|
||||
}
|
||||
|
||||
return players.size
|
||||
@ -1530,104 +1491,73 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
WitherBoss.LIVING_ENTITY_SELECTOR = WitherBoss.LIVING_ENTITY_SELECTOR.and { it.matteryPlayer?.isAndroid != true }
|
||||
}
|
||||
|
||||
val ANDROID_IMMUNE_EFFECTS: TagKey<MobEffect> = TagKey.create(ForgeRegistries.MOB_EFFECTS.registryKey, ResourceLocation(OverdriveThatMatters.MOD_ID, "android_immune_effects"))
|
||||
val ANDROID_IMMUNE_EFFECTS: TagKey<MobEffect> = TagKey.create(BuiltInRegistries.MOB_EFFECT.key(), ResourceLocation(OverdriveThatMatters.MOD_ID, "android_immune_effects"))
|
||||
|
||||
fun onPlayerTick(event: PlayerTickEvent) {
|
||||
val ent = event.player
|
||||
fun onPlayerTickPre(event: PlayerTickEvent.Pre) {
|
||||
val ent = event.entity
|
||||
|
||||
if (event.phase == TickEvent.Phase.START) {
|
||||
if (!ent.level().isClientSide) {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.preTick()
|
||||
ent.matteryPlayer.preTick()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
fun onPlayerTickPost(event: PlayerTickEvent.Pre) {
|
||||
val ent = event.entity
|
||||
|
||||
if (ent.level().isClientSide) {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.tickClient()
|
||||
}
|
||||
ent.matteryPlayer.tickClient()
|
||||
} else {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.tick()
|
||||
}
|
||||
}
|
||||
ent.matteryPlayer.tick()
|
||||
}
|
||||
}
|
||||
|
||||
fun isMobEffectApplicable(event: MobEffectEvent.Applicable) {
|
||||
event.entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
if (it.isAndroid && ForgeRegistries.MOB_EFFECTS.tags()?.getTag(ANDROID_IMMUNE_EFFECTS)?.stream()?.anyMatch { it == event.effectInstance.effect } == true) {
|
||||
event.result = Event.Result.DENY
|
||||
event.entity.matteryPlayer?.let {
|
||||
if (it.isAndroid && BuiltInRegistries.MOB_EFFECT.getOrCreateTag(ANDROID_IMMUNE_EFFECTS).any { it == event.effectInstance?.effect }) {
|
||||
event.result = MobEffectEvent.Applicable.Result.DO_NOT_APPLY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onHurtEvent(event: LivingHurtEvent) {
|
||||
event.entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK { it.onHurt(event) }
|
||||
}
|
||||
|
||||
fun onAttackEvent(event: LivingAttackEvent) {
|
||||
event.entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK { it.onAttack(event) }
|
||||
}
|
||||
|
||||
val CAPABILITY_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, "player")
|
||||
|
||||
fun onAttachCapabilityEvent(event: AttachCapabilitiesEvent<Entity>) {
|
||||
val ent = event.`object`
|
||||
|
||||
if (ent is Player) {
|
||||
event.addCapability(CAPABILITY_LOCATION, MatteryPlayerCapability(ent))
|
||||
}
|
||||
fun onHurtEvent(event: LivingIncomingDamageEvent) {
|
||||
event.entity.matteryPlayer?.onHurt(event)
|
||||
}
|
||||
|
||||
fun onPlayerChangeDimensionEvent(event: PlayerEvent.PlayerChangedDimensionEvent) {
|
||||
onceServer {
|
||||
event.entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.invalidateNetworkState()
|
||||
it.recreateExoPackMenu()
|
||||
}
|
||||
event.entity.matteryPlayer.invalidateNetworkState()
|
||||
event.entity.matteryPlayer.recreateExoPackMenu()
|
||||
}
|
||||
}
|
||||
|
||||
fun onPlayerDeath(event: LivingDeathEvent) {
|
||||
val ply = event.entity as? Player ?: return
|
||||
val mattery = ply.matteryPlayer ?: return
|
||||
|
||||
if (mattery.lastDeathTick != ply.tickCount) {
|
||||
mattery.lastDeathTick = ply.tickCount
|
||||
if (ply.matteryPlayer.lastDeathTick != ply.tickCount) {
|
||||
ply.matteryPlayer.lastDeathTick = ply.tickCount
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
if (!mattery.isAndroid) {
|
||||
if (!ply.matteryPlayer.isAndroid) {
|
||||
return
|
||||
}
|
||||
|
||||
mattery.iteration++
|
||||
mattery.shouldSendIteration = true
|
||||
mattery.deathLog.addLast(ply.tickCount to ply.combatTracker.deathMessage)
|
||||
ply.matteryPlayer.iteration++
|
||||
ply.matteryPlayer.shouldSendIteration = true
|
||||
ply.matteryPlayer.deathLog.addLast(ply.tickCount to ply.combatTracker.deathMessage)
|
||||
|
||||
if (mattery.androidEnergy.batteryLevel < AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2"))
|
||||
mattery.androidEnergy.batteryLevel = AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2") // если смерть была от разряда батареи, то предотвращаем софтлок
|
||||
if (ply.matteryPlayer.androidEnergy.batteryLevel < AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2"))
|
||||
ply.matteryPlayer.androidEnergy.batteryLevel = AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2") // если смерть была от разряда батареи, то предотвращаем софтлок
|
||||
|
||||
while (mattery.deathLog.size > 6) {
|
||||
mattery.deathLog.removeFirst()
|
||||
while (ply.matteryPlayer.deathLog.size > 6) {
|
||||
ply.matteryPlayer.deathLog.removeFirst()
|
||||
}
|
||||
}
|
||||
|
||||
fun onPlayerCloneEvent(event: PlayerEvent.Clone) {
|
||||
val it = event.entity.matteryPlayer ?: return
|
||||
var original = event.original.matteryPlayer
|
||||
|
||||
if (original == null) {
|
||||
event.original.reviveCaps()
|
||||
original = event.original.matteryPlayer
|
||||
}
|
||||
|
||||
if (original == null) {
|
||||
event.original.invalidateCaps()
|
||||
return
|
||||
}
|
||||
val it = event.entity.matteryPlayer
|
||||
val original = event.original.matteryPlayer
|
||||
|
||||
if (original.willBecomeAndroid && event.isWasDeath) {
|
||||
original.becomeAndroid()
|
||||
@ -1640,15 +1570,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
}
|
||||
|
||||
it.deserializeNBT(original.serializeNBT())
|
||||
it.deserializeNBT(original.serializeNBT(it.ply.registryAccess()), it.ply.registryAccess())
|
||||
it.invalidateNetworkState()
|
||||
event.original.invalidateCaps()
|
||||
|
||||
onceServer {
|
||||
event.entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.invalidateNetworkState()
|
||||
it.recreateExoPackMenu()
|
||||
}
|
||||
event.entity.matteryPlayer.invalidateNetworkState()
|
||||
event.entity.matteryPlayer.recreateExoPackMenu()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1661,7 +1588,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
*/
|
||||
@JvmStatic
|
||||
fun phantomSpawnHook(iterator: Iterator<Player>): Iterator<Player> {
|
||||
return iterator.filter { it.matteryPlayer?.isAndroid != true }
|
||||
return iterator.filter { it.matteryPlayer.isAndroid != true }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1673,9 +1600,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
return iterator
|
||||
}
|
||||
|
||||
val mattery = entity.matteryPlayer ?: return iterator
|
||||
|
||||
if (mattery.isAndroid) {
|
||||
if (entity.matteryPlayer.isAndroid) {
|
||||
return iterator.filter {
|
||||
it.first.effect != MobEffects.HUNGER
|
||||
}
|
||||
@ -1686,7 +1611,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
@JvmStatic
|
||||
fun inventoryDropAll(inventory: Inventory) {
|
||||
val mattery = inventory.player.matteryPlayer ?: return
|
||||
val mattery = inventory.player.matteryPlayer
|
||||
|
||||
if (!mattery.hasExopack) {
|
||||
return
|
||||
@ -1724,19 +1649,17 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
@JvmStatic
|
||||
fun playerDestroyVanishingCursedItems(player: Player) {
|
||||
player.matteryPlayer?.let {
|
||||
if (it.hasExopack) {
|
||||
it.exopackContainer.vanishCursedItems()
|
||||
it.exopackChargeSlots.vanishCursedItems()
|
||||
if (player.matteryPlayer.hasExopack) {
|
||||
player.matteryPlayer.exopackContainer.vanishCursedItems()
|
||||
player.matteryPlayer.exopackChargeSlots.vanishCursedItems()
|
||||
// it.exoPackEnergy.parent.vanishCursedItems()
|
||||
|
||||
for (smelter in it.smelters) {
|
||||
for (smelter in player.matteryPlayer.smelters) {
|
||||
smelter.input.vanishCursedItems()
|
||||
smelter.output.vanishCursedItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun pickBlockHook(determinedSlot: Int, itemStack: ItemStack) {
|
||||
@ -1746,25 +1669,25 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
return
|
||||
}
|
||||
|
||||
val matteryPlayer = player.matteryPlayer ?: return
|
||||
val matteryPlayer = player.matteryPlayer
|
||||
|
||||
if (!matteryPlayer.hasExopack) {
|
||||
return
|
||||
}
|
||||
|
||||
val targetSlot = player.inventory.suitableHotbarSlot
|
||||
val itemSlot = matteryPlayer.exopackContainer.indexOfFirst { !it.isEmpty && ItemStack.isSameItemSameTags(itemStack, it) }
|
||||
val itemSlot = matteryPlayer.exopackContainer.indexOfFirst { !it.isEmpty && ItemStack.isSameItemSameComponents(itemStack, it) }
|
||||
|
||||
if (itemSlot == -1) {
|
||||
return
|
||||
}
|
||||
|
||||
MatteryPlayerNetworkChannel.sendToServer(PickItemFromInventoryPacket(targetSlot, itemSlot))
|
||||
PacketDistributor.sendToServer(PickItemFromInventoryPacket(targetSlot, itemSlot))
|
||||
}
|
||||
|
||||
fun onStartTracking(event: PlayerEvent.StartTracking) {
|
||||
if (event.target is ServerPlayer) {
|
||||
event.target.matteryPlayer?.let {
|
||||
(event.target as ServerPlayer).matteryPlayer.let {
|
||||
it.remoteSynchers[event.entity as ServerPlayer] = it.publicSyncher.Remote()
|
||||
}
|
||||
}
|
||||
@ -1772,21 +1695,21 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
fun onStopTracking(event: PlayerEvent.StopTracking) {
|
||||
if (event.target is ServerPlayer) {
|
||||
event.target.matteryPlayer?.remoteSynchers?.remove(event.entity as ServerPlayer)
|
||||
(event.target as ServerPlayer).matteryPlayer.remoteSynchers.remove(event.entity as ServerPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getProjectileHook(player: Player, weaponItem: ItemStack): ItemStack? {
|
||||
val weapon = weaponItem.item as? ProjectileWeaponItem ?: return null
|
||||
val matteryPlayer = player.matteryPlayer ?: return null
|
||||
val matteryPlayer = player.matteryPlayer
|
||||
|
||||
if (!matteryPlayer.hasExopack) {
|
||||
return null
|
||||
}
|
||||
|
||||
val item = matteryPlayer.exopackContainer.stream().filter(weapon.allSupportedProjectiles).findFirst().orElse(null) ?: return null
|
||||
return ForgeHooks.getProjectile(player, weaponItem, item)
|
||||
return CommonHooks.getProjectile(player, weaponItem, item)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.capability.drive
|
||||
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@ -33,6 +34,6 @@ interface IMatteryDrive<T : StorageStack<T>> : IStorageComponent<T> {
|
||||
val driveCapacity: BigInteger
|
||||
|
||||
// not extending INBTSerializable to avoid serializing it as forgecaps
|
||||
fun serializeNBT(): CompoundTag
|
||||
fun deserializeNBT(nbt: CompoundTag)
|
||||
fun serializeNBT(registry: HolderLookup.Provider): CompoundTag
|
||||
fun deserializeNBT(nbt: CompoundTag, registry: HolderLookup.Provider)
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.HolderLookup.Provider
|
||||
import kotlin.jvm.JvmOverloads
|
||||
import java.util.UUID
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
@ -147,10 +149,10 @@ abstract class AbstractMatteryDrive<T : StorageStack<T>>(
|
||||
return copy
|
||||
}
|
||||
|
||||
protected abstract fun serializeStack(item: T): CompoundTag?
|
||||
protected abstract fun deserializeStack(tag: CompoundTag): T?
|
||||
protected abstract fun serializeStack(item: T, registry: Provider): CompoundTag?
|
||||
protected abstract fun deserializeStack(tag: CompoundTag, registry: Provider): T?
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
override fun serializeNBT(registry: Provider): CompoundTag {
|
||||
val compound = CompoundTag()
|
||||
|
||||
compound["capacity"] = driveCapacity.serializeNBT()
|
||||
@ -160,7 +162,7 @@ abstract class AbstractMatteryDrive<T : StorageStack<T>>(
|
||||
compound["items"] = list
|
||||
|
||||
for (tuple in stack2tuples.values) {
|
||||
val serialized = serializeStack(tuple.stack)
|
||||
val serialized = serializeStack(tuple.stack, registry)
|
||||
|
||||
if (serialized != null) {
|
||||
list.add(serialized)
|
||||
@ -170,7 +172,7 @@ abstract class AbstractMatteryDrive<T : StorageStack<T>>(
|
||||
return compound
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
override fun deserializeNBT(nbt: CompoundTag, registry: HolderLookup.Provider) {
|
||||
for (listener in listeners) {
|
||||
for (get in stack2tuples.values) {
|
||||
listener.onStackRemoved(get.id)
|
||||
@ -183,12 +185,12 @@ abstract class AbstractMatteryDrive<T : StorageStack<T>>(
|
||||
storedDifferentStacks = 0
|
||||
// nextID = 0L
|
||||
|
||||
driveCapacity = nbt.map("capacity", ::BigInteger) ?: driveCapacity
|
||||
driveCapacity = nbt.get("capacity")?.let { BigInteger(it) } ?: driveCapacity
|
||||
maxDifferentStacks = nbt.getInt("max_different_stacks")
|
||||
|
||||
for (entry in nbt.getList("items", Tag.TAG_COMPOUND.toInt())) {
|
||||
if (entry is CompoundTag) {
|
||||
val stack = deserializeStack(entry)
|
||||
val stack = deserializeStack(entry, registry)
|
||||
|
||||
if (stack != null && stack.isNotEmpty) {
|
||||
storedCount += stack.count
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user