1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 20:20:30 +00:00

Add MoreRed support

I've written three or four integrations with bundled cables now over the
various versions, and I'm still not convinced this one is right. It
appears to work though, so we'll see.

We need depend on the main jar here (rather than the API jar), as
otherwise our javadoc tools fails - the API references some internal
classes which aren't on our classpath.

It might be nice to write tests for this (and CT) in the future -
goodness knows these features are fragile - but that'll require some
more gradle work which I don't want to do right now.

Closes #772
This commit is contained in:
Jonathan Coates 2021-06-05 14:48:38 +01:00
parent 5eec7d9172
commit db2cde4a4c
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
6 changed files with 165 additions and 23 deletions

View File

@ -53,6 +53,9 @@ minecraft {
property 'forge.logging.markers', 'REGISTRIES' property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug' property 'forge.logging.console.level', 'debug'
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"
mods { mods {
computercraft { computercraft {
source sourceSets.main source sourceSets.main
@ -138,6 +141,7 @@ dependencies {
compileOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104:api") compileOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104:api")
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.5:7.1.0.313") compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.5:7.1.0.313")
compileOnly fg.deobf("commoble.morered:morered-1.16.5:2.1.1.0")
runtimeOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104") runtimeOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104")
@ -180,12 +184,12 @@ task luaJavadoc(type: Javadoc) {
jar { jar {
manifest { manifest {
attributes(["Specification-Title": "computercraft", attributes(["Specification-Title" : "computercraft",
"Specification-Vendor": "SquidDev", "Specification-Vendor" : "SquidDev",
"Specification-Version": "1", "Specification-Version" : "1",
"Implementation-Title": "CC: Tweaked", "Implementation-Title" : "CC: Tweaked",
"Implementation-Version": "${mod_version}", "Implementation-Version" : "${mod_version}",
"Implementation-Vendor" :"SquidDev", "Implementation-Vendor" : "SquidDev",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")]) "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")])
} }
@ -211,7 +215,7 @@ processResources {
["git", "-C", projectDir, "log", "--format=tformat:%an%n%cn"].execute().text.split('\n').each { ["git", "-C", projectDir, "log", "--format=tformat:%an%n%cn"].execute().text.split('\n').each {
if (!blacklist.contains(it)) contributors.add(it) if (!blacklist.contains(it)) contributors.add(it)
} }
} catch(Exception e) { } catch (Exception e) {
e.printStackTrace() e.printStackTrace()
} }
inputs.property "commithash", hash inputs.property "commithash", hash
@ -233,6 +237,9 @@ processResources {
// Web tasks // Web tasks
import com.hierynomus.gradle.license.tasks.LicenseCheck
import com.hierynomus.gradle.license.tasks.LicenseFormat
import org.apache.tools.ant.taskdefs.condition.Os import org.apache.tools.ant.taskdefs.condition.Os
List<String> mkCommand(String command) { List<String> mkCommand(String command) {
@ -302,10 +309,6 @@ jacocoTestReport {
check.dependsOn jacocoTestReport check.dependsOn jacocoTestReport
import com.hierynomus.gradle.license.tasks.LicenseCheck
import com.hierynomus.gradle.license.tasks.LicenseFormat
license { license {
mapping("java", "SLASHSTAR_STYLE") mapping("java", "SLASHSTAR_STYLE")
strictCheck true strictCheck true
@ -335,8 +338,8 @@ gradle.projectsEvaluated {
} }
task licenseAPI(type: LicenseCheck); task licenseAPI(type: LicenseCheck)
task licenseFormatAPI(type: LicenseFormat); task licenseFormatAPI(type: LicenseFormat)
[licenseAPI, licenseFormatAPI].forEach { [licenseAPI, licenseFormatAPI].forEach {
it.configure { it.configure {
source = sourceSets.main.java source = sourceSets.main.java
@ -432,7 +435,7 @@ task checkRelease {
ok = false ok = false
project.logger.error("Must mention the changelog in whatsnew.txt") project.logger.error("Must mention the changelog in whatsnew.txt")
} else { } else {
whatsnew = whatsnew.getAt(0 ..< idx) whatsnew = whatsnew.getAt(0..<idx)
} }
// Check whatsnew and changelog match. // Check whatsnew and changelog match.

View File

@ -13,20 +13,19 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.LinkedHashSet; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
public final class BundledRedstone public final class BundledRedstone
{ {
private static final Set<IBundledRedstoneProvider> providers = new LinkedHashSet<>(); private static final ArrayList<IBundledRedstoneProvider> providers = new ArrayList<>();
private BundledRedstone() {} private BundledRedstone() {}
public static synchronized void register( @Nonnull IBundledRedstoneProvider provider ) public static synchronized void register( @Nonnull IBundledRedstoneProvider provider )
{ {
Objects.requireNonNull( provider, "provider cannot be null" ); Objects.requireNonNull( provider, "provider cannot be null" );
providers.add( provider ); if( !providers.contains( provider ) ) providers.add( provider );
} }
public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )

View File

@ -25,6 +25,7 @@ import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe;
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition; import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
import dan200.computercraft.shared.data.HasComputerIdLootCondition; import dan200.computercraft.shared.data.HasComputerIdLootCondition;
import dan200.computercraft.shared.data.PlayerCreativeLootCondition; import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
import dan200.computercraft.shared.integration.morered.MoreRedIntegration;
import dan200.computercraft.shared.media.items.ItemDisk; import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.media.items.ItemPrintout; import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.media.items.ItemTreasureDisk; import dan200.computercraft.shared.media.items.ItemTreasureDisk;
@ -85,6 +86,7 @@ import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fml.DeferredWorkQueue; import net.minecraftforge.fml.DeferredWorkQueue;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
@ -387,6 +389,9 @@ public final class Registry
ComputerCraftAPI.registerGenericCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ); ComputerCraftAPI.registerGenericCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY );
ComputerCraftAPI.registerGenericCapability( CapabilityEnergy.ENERGY ); ComputerCraftAPI.registerGenericCapability( CapabilityEnergy.ENERGY );
ComputerCraftAPI.registerGenericCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ); ComputerCraftAPI.registerGenericCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY );
// Mod integration code.
if( ModList.get().isLoaded( MoreRedIntegration.MOD_ID ) ) MoreRedIntegration.initialise();
} }
public static void registerLoot() public static void registerLoot()

View File

@ -0,0 +1,124 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration.morered;
import commoble.morered.api.ChanneledPowerSupplier;
import commoble.morered.api.MoreRedAPI;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.shared.common.IBundledRedstoneBlock;
import dan200.computercraft.shared.util.CapabilityUtil;
import dan200.computercraft.shared.util.FixedPointTileEntityType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class MoreRedIntegration
{
public static final String MOD_ID = "morered";
private static final ResourceLocation ID = new ResourceLocation( ComputerCraft.MOD_ID, "morered" );
private static final class BundledPowerSupplier implements ICapabilityProvider, ChanneledPowerSupplier
{
private final IBundledRedstoneBlock block;
private final TileEntity tile;
private LazyOptional<ChanneledPowerSupplier> instance;
private BundledPowerSupplier( IBundledRedstoneBlock block, TileEntity tile )
{
this.block = block;
this.tile = tile;
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> cap, @Nullable Direction side )
{
if( cap != MoreRedAPI.CHANNELED_POWER_CAPABILITY ) return LazyOptional.empty();
if( tile.isRemoved() || !block.getBundledRedstoneConnectivity( tile.getLevel(), tile.getBlockPos(), side ) )
{
return LazyOptional.empty();
}
return (instance == null ? (instance = LazyOptional.of( () -> this )) : instance).cast();
}
@Override
public int getPowerOnChannel( @Nonnull World world, @Nonnull BlockPos wirePos, @Nonnull BlockState wireState, @Nullable Direction wireFace, int channel )
{
if( wireFace == null ) return 0;
BlockPos pos = wirePos.relative( wireFace );
BlockState state = world.getBlockState( pos );
if( !(state.getBlock() instanceof IBundledRedstoneBlock) ) return 0;
IBundledRedstoneBlock block = (IBundledRedstoneBlock) state.getBlock();
return (block.getBundledRedstoneOutput( world, pos, wireFace.getOpposite() ) & (1 << channel)) != 0 ? 31 : 0;
}
void invalidate()
{
instance = CapabilityUtil.invalidate( instance );
}
}
@SubscribeEvent
public static void attachBlockCapabilities( AttachCapabilitiesEvent<TileEntity> event )
{
TileEntity tile = event.getObject();
if( !(tile.getType() instanceof FixedPointTileEntityType) ) return;
Block block = ((FixedPointTileEntityType<?>) tile.getType()).getBlock();
if( !(block instanceof IBundledRedstoneBlock) ) return;
BundledPowerSupplier provider = new BundledPowerSupplier( (IBundledRedstoneBlock) block, tile );
event.addCapability( ID, provider );
event.addListener( provider::invalidate );
}
public static void initialise()
{
MinecraftForge.EVENT_BUS.register( MoreRedIntegration.class );
ComputerCraftAPI.registerBundledRedstoneProvider( MoreRedIntegration::getBundledPower );
}
private static int getBundledPower( World world, BlockPos pos, Direction side )
{
TileEntity tile = world.getBlockEntity( pos );
if( tile == null ) return -1;
ChanneledPowerSupplier power = CapabilityUtil.unwrapUnsafe( tile.getCapability( MoreRedAPI.CHANNELED_POWER_CAPABILITY, side ) );
if( power == null ) return -1;
BlockState state = tile.getBlockState();
// Skip ones already handled by CC. We can do this more efficiently.
if( state.getBlock() instanceof IBundledRedstoneBlock ) return -1;
int mask = 0;
for( int i = 0; i < 16; i++ )
{
mask |= power.getPowerOnChannel( world, pos, state, side, i ) > 0 ? (1 << i) : 0;
}
return mask;
}
}

View File

@ -43,4 +43,10 @@ public final class CapabilityUtil
p.addListener( invalidate ); p.addListener( invalidate );
return p.orElseThrow( NullPointerException::new ); return p.orElseThrow( NullPointerException::new );
} }
@Nullable
public static <T> T unwrapUnsafe( LazyOptional<T> p )
{
return !p.isPresent() ? null : p.orElseThrow( NullPointerException::new );
}
} }

View File

@ -40,6 +40,11 @@ public final class FixedPointTileEntityType<T extends TileEntity> extends TileEn
return block == this.block.get(); return block == this.block.get();
} }
public Block getBlock()
{
return block.get();
}
private static final class FixedPointSupplier<T extends TileEntity> implements Supplier<T> private static final class FixedPointSupplier<T extends TileEntity> implements Supplier<T>
{ {
final FixedPointTileEntityType<T> factory; final FixedPointTileEntityType<T> factory;