Skip to content

Commit 9aeb547

Browse files
committedJun 18, 2016
Turned fallback IAudioSource and IAudioReceivers into capabilities.
Made sound card work with cables and speakers without Charset. Added compatibility with OpenComputers' Colored. Turned IColorable into a capability.
1 parent f218ca3 commit 9aeb547

16 files changed

+518
-78
lines changed
 

‎src/main/java/pl/asie/computronics/Computronics.java

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import pl.asie.computronics.network.NetworkHandlerClient;
5353
import pl.asie.computronics.network.NetworkHandlerServer;
5454
import pl.asie.computronics.oc.IntegrationOpenComputers;
55+
import pl.asie.computronics.reference.Capabilities;
5556
import pl.asie.computronics.reference.Compat;
5657
import pl.asie.computronics.reference.Config;
5758
import pl.asie.computronics.reference.Mods;
@@ -325,6 +326,8 @@ public void init(FMLInitializationEvent event) {
325326
achievements = new ComputronicsAchievements();
326327
achievements.initialize();
327328

329+
Capabilities.INSTANCE.init();
330+
328331
proxy.init();
329332
config.save();
330333
}

‎src/main/java/pl/asie/computronics/integration/charset/audio/IntegrationCharsetAudio.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing faci
5555

5656
@Nullable
5757
@Override
58-
@SuppressWarnings("unchecked")
5958
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
60-
return capability == RECEIVER_CAPABILITY ? (T) sink : null;
59+
return capability == RECEIVER_CAPABILITY ? RECEIVER_CAPABILITY.<T>cast(sink) : null;
6160
}
6261
});
6362
} else if(event.getTileEntity() instanceof TileAudioCable
@@ -73,14 +72,13 @@ public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing faci
7372

7473
@Nullable
7574
@Override
76-
@SuppressWarnings("unchecked")
7775
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
7876
if(capability == RECEIVER_CAPABILITY && facing != null) {
7977
if(RECEIVERS[facing.ordinal()] == null) {
8078
RECEIVERS[facing.ordinal()] = new AudioReceiverCable(cable, facing);
8179
}
8280

83-
return (T) RECEIVERS[facing.ordinal()];
81+
return RECEIVER_CAPABILITY.cast(RECEIVERS[facing.ordinal()]);
8482
} else {
8583
return null;
8684
}

‎src/main/java/pl/asie/computronics/integration/charset/wires/ComputronicsBundledRedstoneIntegration.java

+29-21
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import pl.asie.computronics.util.internal.IComputronicsPeripheral;
1717
import pl.asie.lib.api.tile.IBundledRedstoneProvider;
1818

19+
import javax.annotation.Nullable;
20+
1921
/**
2022
* @author Vexatos
2123
*/
@@ -78,7 +80,7 @@ public static class TileCache {
7880
protected final TileEntity tile;
7981
protected final IBundledRedstoneProvider br;
8082

81-
protected TileCache(TileEntity tile, EnumFacing side) {
83+
protected TileCache(TileEntity tile, @Nullable EnumFacing side) {
8284
this.tile = tile;
8385
this.br = (IBundledRedstoneProvider) tile;
8486
this.side = side;
@@ -87,7 +89,7 @@ protected TileCache(TileEntity tile, EnumFacing side) {
8789

8890
public static class ComputronicsBundledEmitter extends TileCache implements IBundledEmitter {
8991

90-
protected ComputronicsBundledEmitter(TileEntity tile, EnumFacing side) {
92+
protected ComputronicsBundledEmitter(TileEntity tile, @Nullable EnumFacing side) {
9193
super(tile, side);
9294
}
9395

@@ -99,14 +101,14 @@ public byte[] getBundledSignal() {
99101

100102
public static class ComputronicsBundledReceiver extends TileCache implements IBundledReceiver {
101103

102-
protected ComputronicsBundledReceiver(TileEntity tile, EnumFacing side) {
104+
protected ComputronicsBundledReceiver(TileEntity tile, @Nullable EnumFacing side) {
103105
super(tile, side);
104106
}
105107

106108
@Override
107109
public void onBundledInputChange() {
108110
TileEntity tile = this.tile.getWorld().getTileEntity(this.tile.getPos().offset(side));
109-
if(tile.hasCapability(CHARSET_EMITTER, side)) {
111+
if(tile != null && tile.hasCapability(CHARSET_EMITTER, side)) {
110112
br.onBundledInputChange(side, tile.getCapability(CHARSET_EMITTER, side).getBundledSignal());
111113
}
112114
}
@@ -116,45 +118,51 @@ private static class CharsetCapabilityProvider implements ICapabilityProvider {
116118

117119
private final TileEntity tile;
118120
private final IBundledRedstoneProvider br;
119-
private final ComputronicsBundledEmitter[] EMITTERS = new ComputronicsBundledEmitter[6];
120-
private final ComputronicsBundledReceiver[] RECEIVERS = new ComputronicsBundledReceiver[6];
121+
private final ComputronicsBundledEmitter[] EMITTERS = new ComputronicsBundledEmitter[7];
122+
private final ComputronicsBundledReceiver[] RECEIVERS = new ComputronicsBundledReceiver[7];
121123

122124
public CharsetCapabilityProvider(TileEntity tile) {
123125
this.tile = tile;
124126
this.br = ((IBundledRedstoneProvider) tile);
125127
}
126128

127129
@Override
128-
public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
129-
return (capability != null) &&
130-
((capability == CHARSET_EMITTER
131-
&& br.canBundledConnectToOutput(facing)) ||
132-
((capability == CHARSET_RECEIVER)
133-
&& br.canBundledConnectToInput(facing)));
130+
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
131+
return capability == CHARSET_EMITTER && br.canBundledConnectToOutput(facing)
132+
|| capability == CHARSET_RECEIVER && br.canBundledConnectToInput(facing);
134133
}
135134

135+
@Nullable
136136
@Override
137-
@SuppressWarnings("unchecked")
138-
public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
139-
if(capability == null) {
140-
return null;
141-
}
137+
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
142138
if(capability == CHARSET_EMITTER && br.canBundledConnectToOutput(facing)) {
143-
return (T) getEmitter(facing);
139+
return CHARSET_EMITTER.cast(getEmitter(facing));
144140
} else if(capability == CHARSET_RECEIVER && br.canBundledConnectToInput(facing)) {
145-
return (T) getReceiver(facing);
141+
return CHARSET_RECEIVER.cast(getReceiver(facing));
146142
}
147143
return null;
148144
}
149145

150-
private ComputronicsBundledEmitter getEmitter(EnumFacing facing) {
146+
private ComputronicsBundledEmitter getEmitter(@Nullable EnumFacing facing) {
147+
if(facing == null) {
148+
if(EMITTERS[6] == null) {
149+
EMITTERS[6] = new ComputronicsBundledEmitter(tile, null);
150+
}
151+
return EMITTERS[6];
152+
}
151153
if(EMITTERS[facing.ordinal()] == null) {
152154
EMITTERS[facing.ordinal()] = new ComputronicsBundledEmitter(tile, facing);
153155
}
154156
return EMITTERS[facing.ordinal()];
155157
}
156158

157-
private ComputronicsBundledReceiver getReceiver(EnumFacing facing) {
159+
private ComputronicsBundledReceiver getReceiver(@Nullable EnumFacing facing) {
160+
if(facing == null) {
161+
if(RECEIVERS[6] == null) {
162+
RECEIVERS[6] = new ComputronicsBundledReceiver(tile, null);
163+
}
164+
return RECEIVERS[6];
165+
}
158166
if(RECEIVERS[facing.ordinal()] == null) {
159167
RECEIVERS[facing.ordinal()] = new ComputronicsBundledReceiver(tile, facing);
160168
}

‎src/main/java/pl/asie/computronics/oc/driver/DriverCardSound.java

+50-16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import li.cil.oc.api.Network;
44
import li.cil.oc.api.driver.DeviceInfo;
5+
import li.cil.oc.api.internal.Rotatable;
56
import li.cil.oc.api.machine.Arguments;
67
import li.cil.oc.api.machine.Callback;
78
import li.cil.oc.api.machine.Context;
@@ -36,6 +37,7 @@
3637
import pl.asie.computronics.integration.charset.audio.IntegrationCharsetAudio;
3738
import pl.asie.computronics.reference.Config;
3839
import pl.asie.computronics.reference.Mods;
40+
import pl.asie.computronics.util.ColorUtils;
3941
import pl.asie.computronics.util.OCUtils;
4042
import pl.asie.computronics.util.sound.AudioType;
4143
import pl.asie.computronics.util.sound.AudioUtil;
@@ -51,6 +53,7 @@
5153
import pl.asie.computronics.util.sound.Instruction.SetFM;
5254
import pl.asie.computronics.util.sound.Instruction.SetVolume;
5355
import pl.asie.computronics.util.sound.Instruction.SetWave;
56+
import pl.asie.lib.util.internal.IColorable;
5457

5558
import javax.annotation.Nullable;
5659
import java.util.ArrayDeque;
@@ -62,6 +65,9 @@
6265
import java.util.Set;
6366
import java.util.WeakHashMap;
6467

68+
import static pl.asie.computronics.reference.Capabilities.AUDIO_RECEIVER_CAPABILITY;
69+
import static pl.asie.computronics.reference.Capabilities.AUDIO_SOURCE_CAPABILITY;
70+
6571
/**
6672
* @author Vexatos, gamax92
6773
*/
@@ -475,14 +481,33 @@ private void sendMusicPacket(Queue<Instruction> instructions) {
475481
SoundCardPacket pkt = new SoundCardPacket(this, (byte) soundVolume, node().address(), instructions);
476482
int receivers = 0;
477483
boolean sent = false;
478-
if(host instanceof TileEntity && Mods.API.hasAPI(Mods.API.CharsetAudio)) {
479-
int oldReceivers = receivers;
480-
receivers += IntegrationCharsetAudio.send(host.world(), ((TileEntity) host).getPos(), pkt, 1.0F, true);
481-
if(receivers > oldReceivers) {
482-
sent = true;
484+
if(host instanceof TileEntity) {
485+
if(Mods.API.hasAPI(Mods.API.CharsetAudio)) {
486+
int oldReceivers = receivers;
487+
receivers += IntegrationCharsetAudio.send(host.world(), ((TileEntity) host).getPos(), pkt, 1.0F, true);
488+
if(receivers > oldReceivers) {
489+
sent = true;
490+
}
483491
}
484492
}
485493
if(!sent) {
494+
if(host instanceof TileEntity) {
495+
for(EnumFacing dir : EnumFacing.VALUES) {
496+
TileEntity tile = host.world().getTileEntity(((TileEntity) host).getPos().offset(dir));
497+
if(tile != null) {
498+
if(tile.hasCapability(AUDIO_RECEIVER_CAPABILITY, dir.getOpposite())) {
499+
IColorable hostCol = ColorUtils.getColorable((TileEntity) host, dir);
500+
IColorable targetCol = ColorUtils.getColorable(tile, dir.getOpposite());
501+
if(hostCol != null && targetCol != null && hostCol.canBeColored() && targetCol.canBeColored()
502+
&& !ColorUtils.isSameOrDefault(hostCol, targetCol)) {
503+
continue;
504+
}
505+
tile.getCapability(AUDIO_RECEIVER_CAPABILITY, dir.getOpposite()).receivePacket(pkt, dir.getOpposite());
506+
receivers++;
507+
}
508+
}
509+
}
510+
}
486511
if(receivers == 0) {
487512
internalSpeaker.receivePacket(pkt, null);
488513
}
@@ -508,37 +533,46 @@ protected void sendSound(Queue<Instruction> buffer) {
508533

509534
@Override
510535
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
536+
facing = host instanceof Rotatable ? ((Rotatable) host).toGlobal(facing) : facing;
511537
if(Mods.API.hasAPI(Mods.API.CharsetAudio)) {
512-
return capability == IntegrationCharsetAudio.SOURCE_CAPABILITY;
513-
} else {
514-
return false;
538+
if(capability == IntegrationCharsetAudio.SOURCE_CAPABILITY && facing != null && connectsAudio(facing)) {
539+
return true;
540+
}
515541
}
542+
return capability == AUDIO_SOURCE_CAPABILITY && facing != null && connectsAudio(facing);
516543
}
517544

518545
private Object charsetAudioSource;
519546

520547
@Nullable
521548
@Override
522-
@SuppressWarnings("unchecked")
523549
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
550+
facing = host instanceof Rotatable ? ((Rotatable) host).toGlobal(facing) : facing;
524551
if(Mods.API.hasAPI(Mods.API.CharsetAudio)) {
525-
if(capability == IntegrationCharsetAudio.SOURCE_CAPABILITY) {
552+
if(capability == IntegrationCharsetAudio.SOURCE_CAPABILITY && facing != null && connectsAudio(facing)) {
526553
if(charsetAudioSource == null) {
527554
charsetAudioSource = new pl.asie.charset.api.audio.IAudioSource() {
528555
};
529556
}
530-
return (T) charsetAudioSource;
531-
} else {
532-
return null;
557+
return IntegrationCharsetAudio.SOURCE_CAPABILITY.cast((pl.asie.charset.api.audio.IAudioSource) charsetAudioSource);
533558
}
534-
} else {
535-
return null;
536559
}
560+
if(capability == AUDIO_SOURCE_CAPABILITY && facing != null && connectsAudio(facing)) {
561+
return AUDIO_SOURCE_CAPABILITY.cast(this);
562+
}
563+
return null;
537564
}
538565

539566
@Override
540567
public boolean connectsAudio(EnumFacing side) {
541-
return false;
568+
if(host instanceof TileEntity) {
569+
IColorable hostCol = ColorUtils.getColorable((TileEntity) host, side);
570+
IColorable targetCol = ColorUtils.getColorable(host.world().getTileEntity(((TileEntity) host).getPos().offset(side)), side.getOpposite());
571+
if(hostCol != null && targetCol != null && hostCol.canBeColored() && targetCol.canBeColored()) {
572+
return ColorUtils.isSameOrDefault(hostCol, targetCol);
573+
}
574+
}
575+
return true;
542576
}
543577

544578
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
package pl.asie.computronics.reference;
2+
3+
import net.minecraft.nbt.NBTBase;
4+
import net.minecraft.tileentity.TileEntity;
5+
import net.minecraft.util.EnumFacing;
6+
import net.minecraft.util.ResourceLocation;
7+
import net.minecraft.util.math.BlockPos;
8+
import net.minecraft.world.World;
9+
import net.minecraftforge.common.MinecraftForge;
10+
import net.minecraftforge.common.capabilities.Capability;
11+
import net.minecraftforge.common.capabilities.CapabilityInject;
12+
import net.minecraftforge.common.capabilities.CapabilityManager;
13+
import net.minecraftforge.common.capabilities.ICapabilityProvider;
14+
import net.minecraftforge.event.AttachCapabilitiesEvent;
15+
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
16+
import pl.asie.computronics.api.audio.AudioPacket;
17+
import pl.asie.computronics.api.audio.IAudioReceiver;
18+
import pl.asie.computronics.api.audio.IAudioSource;
19+
20+
import javax.annotation.Nullable;
21+
22+
/**
23+
* @author Vexatos
24+
*/
25+
public class Capabilities {
26+
27+
public static final Capabilities INSTANCE = new Capabilities();
28+
29+
@CapabilityInject(IAudioSource.class)
30+
public static Capability<IAudioSource> AUDIO_SOURCE_CAPABILITY;
31+
@CapabilityInject(IAudioReceiver.class)
32+
public static Capability<IAudioReceiver> AUDIO_RECEIVER_CAPABILITY;
33+
34+
private static final ResourceLocation AUDIO_SOURCE_KEY = new ResourceLocation("computronics:audio_source");
35+
private static final ResourceLocation AUDIO_RECEIVER_KEY = new ResourceLocation("computronics:audio_receiver");
36+
37+
public void init() {
38+
MinecraftForge.EVENT_BUS.register(this);
39+
CapabilityManager.INSTANCE.register(IAudioSource.class, new NullCapabilityStorage<IAudioSource>(), DefaultAudioSource.class);
40+
CapabilityManager.INSTANCE.register(IAudioReceiver.class, new NullCapabilityStorage<IAudioReceiver>(), DefaultAudioReceiver.class);
41+
}
42+
43+
public static boolean hasAny(@Nullable ICapabilityProvider provider, EnumFacing dir, Capability... caps) {
44+
if(provider == null) {
45+
return false;
46+
}
47+
for(Capability cap : caps) {
48+
if(provider.hasCapability(cap, dir)) {
49+
return true;
50+
}
51+
}
52+
return false;
53+
}
54+
55+
public static boolean hasAll(@Nullable ICapabilityProvider provider, EnumFacing dir, Capability... caps) {
56+
if(provider == null) {
57+
return false;
58+
}
59+
for(Capability cap : caps) {
60+
if(!provider.hasCapability(cap, dir)) {
61+
return false;
62+
}
63+
}
64+
return true;
65+
}
66+
67+
@Nullable
68+
public static <T> T getFirst(@Nullable ICapabilityProvider provider, EnumFacing dir, Iterable<Capability<? extends T>> caps) {
69+
if(provider == null) {
70+
return null;
71+
}
72+
for(Capability<? extends T> cap : caps) {
73+
if(provider.hasCapability(cap, dir)) {
74+
return provider.getCapability(cap, dir);
75+
}
76+
}
77+
return null;
78+
}
79+
80+
@Nullable
81+
public static <T> T getFirst(@Nullable ICapabilityProvider provider, EnumFacing dir, Capability<? extends T> first, Capability<? extends T> second) {
82+
if(provider == null) {
83+
return null;
84+
}
85+
if(provider.hasCapability(first, dir)) {
86+
return provider.getCapability(first, dir);
87+
}
88+
if(provider.hasCapability(second, dir)) {
89+
return provider.getCapability(second, dir);
90+
}
91+
return null;
92+
}
93+
94+
@SubscribeEvent
95+
public void onAttachCapabilities(AttachCapabilitiesEvent.TileEntity e) {
96+
final TileEntity tile = e.getTileEntity();
97+
if(tile instanceof IAudioSource) {
98+
e.addCapability(AUDIO_SOURCE_KEY, new ICapabilityProvider() {
99+
@Override
100+
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
101+
return capability == AUDIO_SOURCE_CAPABILITY;
102+
}
103+
104+
@Nullable
105+
@Override
106+
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
107+
return hasCapability(capability, facing) ? AUDIO_SOURCE_CAPABILITY.<T>cast((IAudioSource) tile) : null;
108+
}
109+
});
110+
}
111+
if(tile instanceof IAudioReceiver) {
112+
e.addCapability(AUDIO_RECEIVER_KEY, new ICapabilityProvider() {
113+
@Override
114+
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
115+
return capability == AUDIO_RECEIVER_CAPABILITY;
116+
}
117+
118+
@Nullable
119+
@Override
120+
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
121+
return hasCapability(capability, facing) ? AUDIO_RECEIVER_CAPABILITY.<T>cast((IAudioReceiver) tile) : null;
122+
}
123+
});
124+
}
125+
}
126+
127+
/**
128+
* @author asie
129+
*/
130+
public static class NullCapabilityStorage<T> implements Capability.IStorage<T> {
131+
132+
public NullCapabilityStorage() {
133+
}
134+
135+
@Nullable
136+
@Override
137+
public NBTBase writeNBT(Capability<T> capability, T instance, EnumFacing side) {
138+
return null;
139+
}
140+
141+
@Override
142+
public void readNBT(Capability<T> capability, T instance, EnumFacing side, NBTBase nbt) {
143+
}
144+
}
145+
146+
private static class DefaultAudioSource implements IAudioSource {
147+
148+
@Override
149+
public int getSourceId() {
150+
return -1;
151+
}
152+
153+
@Override
154+
public boolean connectsAudio(EnumFacing side) {
155+
return false;
156+
}
157+
}
158+
159+
private static class DefaultAudioReceiver implements IAudioReceiver {
160+
161+
@Nullable
162+
@Override
163+
public World getSoundWorld() {
164+
return null;
165+
}
166+
167+
@Override
168+
public BlockPos getSoundPos() {
169+
return BlockPos.ORIGIN;
170+
}
171+
172+
@Override
173+
public int getSoundDistance() {
174+
return 0;
175+
}
176+
177+
@Override
178+
public void receivePacket(AudioPacket packet, @Nullable EnumFacing side) {
179+
180+
}
181+
182+
@Override
183+
public boolean connectsAudio(EnumFacing side) {
184+
return false;
185+
}
186+
}
187+
188+
private Capabilities() {
189+
}
190+
}

‎src/main/java/pl/asie/computronics/tile/TileAudioCable.java

+17-6
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@
1010
import pl.asie.computronics.api.audio.IAudioConnection;
1111
import pl.asie.computronics.api.audio.IAudioReceiver;
1212
import pl.asie.computronics.integration.charset.audio.IntegrationCharsetAudio;
13+
import pl.asie.computronics.reference.Capabilities;
1314
import pl.asie.computronics.reference.Mods;
15+
import pl.asie.computronics.util.ColorUtils;
1416
import pl.asie.lib.tile.TileEntityBase;
15-
import pl.asie.lib.util.ColorUtils;
1617
import pl.asie.lib.util.internal.IColorable;
1718

1819
import javax.annotation.Nullable;
1920
import java.util.HashSet;
2021

22+
import static pl.asie.computronics.reference.Capabilities.AUDIO_RECEIVER_CAPABILITY;
23+
import static pl.asie.computronics.reference.Capabilities.AUDIO_SOURCE_CAPABILITY;
24+
2125
public class TileAudioCable extends TileEntityBase implements IAudioReceiver, IColorable, ITickable {
2226

2327
private final HashSet<Object> packetIds = new HashSet<Object>();
@@ -49,13 +53,20 @@ private void updateConnections() {
4953
if(!IntegrationCharsetAudio.connects(tile, dir.getOpposite())) {
5054
continue;
5155
}
56+
} else if(Capabilities.hasAny(tile, dir.getOpposite(), AUDIO_SOURCE_CAPABILITY, AUDIO_RECEIVER_CAPABILITY)) {
57+
IAudioConnection con = Capabilities.getFirst(tile, dir.getOpposite(), AUDIO_SOURCE_CAPABILITY, AUDIO_RECEIVER_CAPABILITY);
58+
if(con == null || !con.connectsAudio(dir)) {
59+
continue;
60+
}
5261
} else {
5362
continue;
5463
}
5564

56-
if(tile instanceof IColorable && ((IColorable) tile).canBeColored()
57-
&& !ColorUtils.isSameOrDefault(this, (IColorable) tile)) {
58-
continue;
65+
IColorable targetCol = ColorUtils.getColorable(tile, dir.getOpposite());
66+
if(targetCol != null) {
67+
if(targetCol.canBeColored() && !ColorUtils.isSameOrDefault(this, targetCol)) {
68+
continue;
69+
}
5970
}
6071

6172
connectionMap |= 1 << dir.ordinal();
@@ -113,8 +124,8 @@ public void receivePacket(AudioPacket packet, @Nullable EnumFacing side) {
113124
}
114125

115126
TileEntity tile = worldObj.getTileEntity(pos);
116-
if(tile instanceof IAudioReceiver) {
117-
((IAudioReceiver) tile).receivePacket(packet, dir.getOpposite());
127+
if(tile != null && tile.hasCapability(AUDIO_RECEIVER_CAPABILITY, dir.getOpposite())) {
128+
tile.getCapability(AUDIO_RECEIVER_CAPABILITY, dir.getOpposite()).receivePacket(packet, dir.getOpposite());
118129
}
119130
}
120131
}

‎src/main/java/pl/asie/computronics/tile/TileCipherBlock.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import pl.asie.lib.api.tile.IBundledRedstoneProvider;
2626
import pl.asie.lib.util.Base64;
2727

28+
import javax.annotation.Nullable;
2829
import javax.crypto.Cipher;
2930
import javax.crypto.spec.IvParameterSpec;
3031
import javax.crypto.spec.SecretKeySpec;
@@ -298,17 +299,18 @@ public void removeFromNBTForTransfer(NBTTagCompound data) {
298299
}
299300

300301
@Override
301-
public boolean canBundledConnectToInput(EnumFacing side) {
302+
public boolean canBundledConnectToInput(@Nullable EnumFacing side) {
302303
return worldObj != null && side == worldObj.getBlockState(getPos()).getValue(Computronics.cipher.rotation.FACING).rotateY();
303304
}
304305

305306
@Override
306-
public boolean canBundledConnectToOutput(EnumFacing side) {
307+
public boolean canBundledConnectToOutput(@Nullable EnumFacing side) {
307308
return worldObj != null && side == worldObj.getBlockState(getPos()).getValue(Computronics.cipher.rotation.FACING).rotateYCCW();
308309
}
309310

311+
@Nullable
310312
@Override
311-
public byte[] getBundledOutput(EnumFacing side) {
313+
public byte[] getBundledOutput(@Nullable EnumFacing side) {
312314
if(side == worldObj.getBlockState(getPos()).getValue(Computronics.cipher.rotation.FACING).rotateYCCW()) {
313315
return getBundledOutput();
314316
} else {
@@ -317,7 +319,7 @@ public byte[] getBundledOutput(EnumFacing side) {
317319
}
318320

319321
@Override
320-
public void onBundledInputChange(EnumFacing side, byte[] data) {
322+
public void onBundledInputChange(@Nullable EnumFacing side, @Nullable byte[] data) {
321323
if(data != null && side == worldObj.getBlockState(getPos()).getValue(Computronics.cipher.rotation.FACING).rotateY()) {
322324
bundledXORData = 0;
323325
for(int i = 0; i < 16; i++) {

‎src/main/java/pl/asie/computronics/tile/TileColorfulLamp.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import pl.asie.computronics.util.OCUtils;
1818
import pl.asie.lib.api.tile.IBundledRedstoneProvider;
1919

20+
import javax.annotation.Nullable;
21+
2022
import static pl.asie.computronics.block.BlockColorfulLamp.BRIGHTNESS;
2123

2224
//import mods.immibis.redlogic.api.wiring.IBundledEmitter;
@@ -123,6 +125,7 @@ public String[] getMethodNames() {
123125
return new String[] { "getLampColor", "setLampColor" };
124126
}
125127

128+
@Nullable
126129
@Override
127130
@Optional.Method(modid = Mods.ComputerCraft)
128131
public Object[] callMethod(IComputerAccess computer, ILuaContext context,
@@ -204,7 +207,7 @@ public void readFromRemoteNBT(NBTTagCompound tag) {
204207
}
205208
}
206209

207-
private boolean parseBundledInput(byte[] data) {
210+
private boolean parseBundledInput(@Nullable byte[] data) {
208211
if(data != null) {
209212
int c = 0;
210213
for(int i = 0; i < 15; i++) {
@@ -220,22 +223,22 @@ private boolean parseBundledInput(byte[] data) {
220223
}
221224

222225
@Override
223-
public boolean canBundledConnectToInput(EnumFacing side) {
226+
public boolean canBundledConnectToInput(@Nullable EnumFacing side) {
224227
return true;
225228
}
226229

227230
@Override
228-
public boolean canBundledConnectToOutput(EnumFacing side) {
231+
public boolean canBundledConnectToOutput(@Nullable EnumFacing side) {
229232
return false;
230233
}
231234

232235
@Override
233-
public byte[] getBundledOutput(EnumFacing side) {
236+
public byte[] getBundledOutput(@Nullable EnumFacing side) {
234237
return new byte[16];
235238
}
236239

237240
@Override
238-
public void onBundledInputChange(EnumFacing side, byte[] data) {
241+
public void onBundledInputChange(@Nullable EnumFacing side, @Nullable byte[] data) {
239242
parseBundledInput(data);
240243
}
241244

‎src/main/java/pl/asie/computronics/tile/TileIronNote.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import pl.asie.computronics.util.OCUtils;
1515
import pl.asie.lib.api.tile.IBundledRedstoneProvider;
1616

17+
import javax.annotation.Nullable;
1718
import java.util.ArrayList;
1819
import java.util.List;
1920

@@ -127,7 +128,7 @@ public Object[] callMethod(IComputerAccess computer, ILuaContext context,
127128
return null;
128129
}
129130

130-
private void parseBundledInput(byte[] data) {
131+
private void parseBundledInput(@Nullable byte[] data) {
131132
int baseNote = 4;
132133
if(data != null) {
133134
for(int i = 0; i < 16; i++) {
@@ -142,22 +143,22 @@ private void parseBundledInput(byte[] data) {
142143
}
143144

144145
@Override
145-
public boolean canBundledConnectToInput(EnumFacing side) {
146+
public boolean canBundledConnectToInput(@Nullable EnumFacing side) {
146147
return true;
147148
}
148149

149150
@Override
150-
public boolean canBundledConnectToOutput(EnumFacing side) {
151+
public boolean canBundledConnectToOutput(@Nullable EnumFacing side) {
151152
return false;
152153
}
153154

154155
@Override
155-
public byte[] getBundledOutput(EnumFacing side) {
156+
public byte[] getBundledOutput(@Nullable EnumFacing side) {
156157
return new byte[16];
157158
}
158159

159160
@Override
160-
public void onBundledInputChange(EnumFacing side, byte[] data) {
161+
public void onBundledInputChange(@Nullable EnumFacing side, @Nullable byte[] data) {
161162
parseBundledInput(data);
162163
}
163164

‎src/main/java/pl/asie/computronics/tile/TileTapeDrive.java

+15-12
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,16 @@
3434
import pl.asie.computronics.reference.Config;
3535
import pl.asie.computronics.reference.Mods;
3636
import pl.asie.computronics.tile.TapeDriveState.State;
37+
import pl.asie.computronics.util.ColorUtils;
3738
import pl.asie.computronics.util.OCUtils;
3839
import pl.asie.lib.network.Packet;
39-
import pl.asie.lib.util.ColorUtils;
4040
import pl.asie.lib.util.internal.IColorable;
4141

4242
import javax.annotation.Nullable;
4343
import java.util.HashMap;
4444

45+
import static pl.asie.computronics.reference.Capabilities.AUDIO_RECEIVER_CAPABILITY;
46+
4547
public class TileTapeDrive extends TileEntityPeripheralBase implements IAudioSource, ITickable {
4648

4749
private final IAudioReceiver internalSpeaker = new IAudioReceiver() {
@@ -284,17 +286,6 @@ public void update() {
284286
AudioPacket pkt = state.update(this, worldObj, getPos());
285287
if(pkt != null) {
286288
int receivers = 0;
287-
for(EnumFacing dir : EnumFacing.VALUES) {
288-
TileEntity tile = worldObj.getTileEntity(getPos().offset(dir));
289-
if(tile instanceof IAudioReceiver) {
290-
if(tile instanceof IColorable && ((IColorable) tile).canBeColored()
291-
&& !ColorUtils.isSameOrDefault(this, (IColorable) tile)) {
292-
continue;
293-
}
294-
((IAudioReceiver) tile).receivePacket(pkt, dir.getOpposite());
295-
receivers++;
296-
}
297-
}
298289

299290
boolean sent = false;
300291
if(Mods.API.hasAPI(Mods.API.CharsetAudio)) {
@@ -306,6 +297,18 @@ public void update() {
306297
}
307298

308299
if(!sent) {
300+
for(EnumFacing dir : EnumFacing.VALUES) {
301+
TileEntity tile = worldObj.getTileEntity(getPos().offset(dir));
302+
if(tile != null && tile.hasCapability(AUDIO_RECEIVER_CAPABILITY, dir.getOpposite())) {
303+
IColorable targetCol = ColorUtils.getColorable(tile, dir.getOpposite());
304+
if(targetCol != null && targetCol.canBeColored()
305+
&& !ColorUtils.isSameOrDefault(this, targetCol)) {
306+
continue;
307+
}
308+
tile.getCapability(AUDIO_RECEIVER_CAPABILITY, dir.getOpposite()).receivePacket(pkt, dir.getOpposite());
309+
receivers++;
310+
}
311+
}
309312
if(receivers == 0) {
310313
internalSpeaker.receivePacket(pkt, null);
311314
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package pl.asie.computronics.util;
2+
3+
import net.minecraft.util.EnumFacing;
4+
import net.minecraftforge.common.capabilities.ICapabilityProvider;
5+
import pl.asie.computronics.reference.Mods;
6+
import pl.asie.lib.util.internal.IColorable;
7+
8+
import javax.annotation.Nullable;
9+
10+
import static pl.asie.lib.reference.Capabilities.COLORABLE_CAPABILITY;
11+
12+
/**
13+
* @author Vexatos
14+
*/
15+
public class ColorUtils extends pl.asie.lib.util.ColorUtils {
16+
17+
@Nullable
18+
public static IColorable getColorable(@Nullable ICapabilityProvider provider, EnumFacing side) {
19+
if(Mods.isLoaded(Mods.OpenComputers)) {
20+
return OCUtils.getColorable(provider, side);
21+
}
22+
if(provider != null && provider.hasCapability(COLORABLE_CAPABILITY, side)) {
23+
return provider.getCapability(COLORABLE_CAPABILITY, side);
24+
}
25+
return null;
26+
}
27+
}

‎src/main/java/pl/asie/computronics/util/NoteUtils.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ public static void playNoteRaw(World worldObj, BlockPos pos, String instrument,
2222
int yCoord = pos.getY();
2323
int zCoord = pos.getZ();
2424

25-
worldObj.playSound(null, (double) xCoord + 0.5D, (double) yCoord + 0.5D, (double) zCoord + 0.5D, SoundEvent.REGISTRY.getObject(new ResourceLocation(instrument)), SoundCategory.BLOCKS, volume, f);
25+
SoundEvent ev = SoundEvent.REGISTRY.getObject(new ResourceLocation(instrument));
26+
if(ev != null) {
27+
worldObj.playSound(null, (double) xCoord + 0.5D, (double) yCoord + 0.5D, (double) zCoord + 0.5D, ev, SoundCategory.BLOCKS, volume, f);
28+
}
2629
ParticleUtils.sendParticlePacket(EnumParticleTypes.NOTE, worldObj, (double) xCoord + 0.5D, (double) yCoord + 1.2D, (double) zCoord + 0.5D, (double) note / 24.0D, 1.0D, 0.0D);
2730
}
2831

‎src/main/java/pl/asie/computronics/util/OCUtils.java

+55
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
package pl.asie.computronics.util;
22

33
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute;
4+
import li.cil.oc.api.internal.Colored;
45
import li.cil.oc.client.KeyBindings;
56
import li.cil.oc.util.ItemCosts;
67
import net.minecraft.client.Minecraft;
78
import net.minecraft.client.gui.FontRenderer;
89
import net.minecraft.item.ItemStack;
910
import net.minecraft.nbt.NBTTagCompound;
11+
import net.minecraft.util.EnumFacing;
1012
import net.minecraft.util.text.TextFormatting;
13+
import net.minecraftforge.common.capabilities.Capability;
14+
import net.minecraftforge.common.capabilities.CapabilityInject;
15+
import net.minecraftforge.common.capabilities.ICapabilityProvider;
1116
import net.minecraftforge.fml.relauncher.Side;
1217
import net.minecraftforge.fml.relauncher.SideOnly;
18+
import pl.asie.lib.util.ColorUtils;
19+
import pl.asie.lib.util.internal.IColorable;
1320

21+
import javax.annotation.Nullable;
1422
import java.util.HashMap;
1523
import java.util.List;
1624
import java.util.Map;
1725

26+
import static pl.asie.lib.reference.Capabilities.COLORABLE_CAPABILITY;
27+
1828
/**
1929
* @author Vexatos
2030
*/
@@ -124,4 +134,49 @@ public static void addTooltip(ItemStack stack, List tooltip) {
124134
}
125135
}
126136

137+
@CapabilityInject(Colored.class)
138+
public static Capability<Colored> COLORED_CAPABILITY;
139+
140+
@Nullable
141+
public static IColorable getColorable(@Nullable ICapabilityProvider provider, EnumFacing side) {
142+
if(provider != null && provider.hasCapability(COLORABLE_CAPABILITY, side)) {
143+
return provider.getCapability(COLORABLE_CAPABILITY, side);
144+
}
145+
if(provider != null && provider.hasCapability(COLORED_CAPABILITY, side)) {
146+
return new ConvertedColorable(provider.getCapability(COLORED_CAPABILITY, side));
147+
}
148+
return null;
149+
}
150+
151+
/**
152+
* @author Vexatos
153+
*/
154+
public static class ConvertedColorable implements IColorable {
155+
156+
private final Colored colored;
157+
158+
public ConvertedColorable(Colored colored) {
159+
this.colored = colored;
160+
}
161+
162+
@Override
163+
public boolean canBeColored() {
164+
return colored.controlsConnectivity();
165+
}
166+
167+
@Override
168+
public int getColor() {
169+
return colored.getColor();
170+
}
171+
172+
@Override
173+
public int getDefaultColor() {
174+
return ColorUtils.Color.LightGray.color;
175+
}
176+
177+
@Override
178+
public void setColor(int color) {
179+
colored.setColor(color);
180+
}
181+
}
127182
}

‎src/main/java/pl/asie/lib/AsieLibMod.java

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import pl.asie.lib.api.tool.IToolRegistry;
1818
import pl.asie.lib.integration.Integration;
1919
import pl.asie.lib.integration.tool.ToolProviders;
20+
import pl.asie.lib.reference.Capabilities;
2021
import pl.asie.lib.reference.Mods;
2122
import pl.asie.lib.tweak.enchantment.EnchantmentTweak;
2223
import pl.asie.lib.util.color.RecipeColorizer;
@@ -82,6 +83,8 @@ public void init(FMLInitializationEvent event) {
8283

8384
RecipeSorter.register("asielib:colorizer", RecipeColorizer.class, RecipeSorter.Category.SHAPELESS, "after:forge:shapelessore");
8485
RecipeSorter.register("asielib:decolorizer", RecipeDecolorizer.class, RecipeSorter.Category.SHAPELESS, "after:asielib:colorizer");
86+
87+
Capabilities.INSTANCE.init();
8588
}
8689

8790
@EventHandler

‎src/main/java/pl/asie/lib/api/tile/IBundledRedstoneProvider.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
import net.minecraft.util.EnumFacing;
1111

12+
import javax.annotation.Nullable;
13+
1214
/*@Optional.InterfaceList({
1315
@Optional.Interface(iface = "mods.immibis.redlogic.api.wiring.IBundledEmitter", modid = Mods.RedLogic),
1416
@Optional.Interface(iface = "mods.immibis.redlogic.api.wiring.IBundledUpdatable", modid = Mods.RedLogic),
@@ -17,11 +19,12 @@
1719
})*/
1820
public interface IBundledRedstoneProvider /*extends IBundledEmitter, IBundledUpdatable, IConnectable, IBundledTile*/ {
1921

20-
public boolean canBundledConnectToInput(EnumFacing side);
22+
public boolean canBundledConnectToInput(@Nullable EnumFacing side);
2123

22-
public boolean canBundledConnectToOutput(EnumFacing side);
24+
public boolean canBundledConnectToOutput(@Nullable EnumFacing side);
2325

24-
public byte[] getBundledOutput(EnumFacing side);
26+
@Nullable
27+
public byte[] getBundledOutput(@Nullable EnumFacing side);
2528

26-
public void onBundledInputChange(EnumFacing side, byte[] data);
29+
public void onBundledInputChange(@Nullable EnumFacing side, @Nullable byte[] data);
2730
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package pl.asie.lib.reference;
2+
3+
import net.minecraft.nbt.NBTBase;
4+
import net.minecraft.nbt.NBTTagInt;
5+
import net.minecraft.tileentity.TileEntity;
6+
import net.minecraft.util.EnumFacing;
7+
import net.minecraft.util.ResourceLocation;
8+
import net.minecraftforge.common.MinecraftForge;
9+
import net.minecraftforge.common.capabilities.Capability;
10+
import net.minecraftforge.common.capabilities.CapabilityInject;
11+
import net.minecraftforge.common.capabilities.CapabilityManager;
12+
import net.minecraftforge.common.capabilities.ICapabilityProvider;
13+
import net.minecraftforge.event.AttachCapabilitiesEvent;
14+
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
15+
import pl.asie.lib.util.internal.IColorable;
16+
17+
import javax.annotation.Nullable;
18+
19+
/**
20+
* @author Vexatos
21+
*/
22+
public class Capabilities {
23+
24+
public static final Capabilities INSTANCE = new Capabilities();
25+
26+
@CapabilityInject(IColorable.class)
27+
public static Capability<IColorable> COLORABLE_CAPABILITY;
28+
private static final ResourceLocation COLORABLE_KEY = new ResourceLocation("computronics:colorable");
29+
30+
public void init() {
31+
MinecraftForge.EVENT_BUS.register(this);
32+
CapabilityManager.INSTANCE.register(IColorable.class, new ColorableStorage(), DefaultColorable.class);
33+
}
34+
35+
@SubscribeEvent
36+
public void onAttachCapabilities(AttachCapabilitiesEvent.TileEntity e) {
37+
final TileEntity tile = e.getTileEntity();
38+
if(tile instanceof IColorable) {
39+
e.addCapability(COLORABLE_KEY, new ICapabilityProvider() {
40+
@Override
41+
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
42+
return capability == COLORABLE_CAPABILITY;
43+
}
44+
45+
@Nullable
46+
@Override
47+
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
48+
return hasCapability(capability, facing) ? COLORABLE_CAPABILITY.<T>cast(((IColorable) tile)) : null;
49+
}
50+
});
51+
}
52+
}
53+
54+
private static class ColorableStorage implements Capability.IStorage<IColorable> {
55+
56+
@Override
57+
public NBTBase writeNBT(Capability<IColorable> capability, IColorable instance, EnumFacing side) {
58+
return new NBTTagInt(instance.getColor());
59+
}
60+
61+
@Override
62+
public void readNBT(Capability<IColorable> capability, IColorable instance, EnumFacing side, NBTBase nbt) {
63+
if(nbt instanceof NBTTagInt) {
64+
instance.setColor(((NBTTagInt) nbt).getInt());
65+
}
66+
}
67+
}
68+
69+
private static class DefaultColorable implements IColorable {
70+
71+
private int color = 0;
72+
73+
@Override
74+
public boolean canBeColored() {
75+
return false;
76+
}
77+
78+
@Override
79+
public int getColor() {
80+
return color;
81+
}
82+
83+
@Override
84+
public int getDefaultColor() {
85+
return 0;
86+
}
87+
88+
@Override
89+
public void setColor(int color) {
90+
this.color = color;
91+
}
92+
}
93+
94+
private Capabilities() {
95+
}
96+
}

0 commit comments

Comments
 (0)
Please sign in to comment.