diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java index 18b951fde..abbcb5e18 100644 --- a/src/main/java/dan200/computercraft/ComputerCraft.java +++ b/src/main/java/dan200/computercraft/ComputerCraft.java @@ -40,6 +40,7 @@ import dan200.computercraft.shared.peripheral.modem.WirelessNetwork; import dan200.computercraft.shared.peripheral.printer.TilePrinter; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.pocket.peripherals.PocketModem; +import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker; import dan200.computercraft.shared.proxy.ICCTurtleProxy; import dan200.computercraft.shared.proxy.IComputerCraftProxy; import dan200.computercraft.shared.turtle.blocks.BlockTurtle; @@ -132,6 +133,8 @@ public class ComputerCraft public static int floppySpaceLimit = 125 * 1000; public static int maximumFilesOpen = 128; + public static int maxNotesPerTick = 8; + // Blocks and Items public static class Blocks { @@ -171,6 +174,7 @@ public class ComputerCraft { public static PocketModem wirelessModem; public static PocketModem advancedModem; + public static PocketSpeaker pocketSpeaker; } public static class Config { @@ -196,6 +200,8 @@ public class ComputerCraft public static Property computerSpaceLimit; public static Property floppySpaceLimit; public static Property maximumFilesOpen; + public static Property maxNotesPerTick; + } // Registries @@ -287,6 +293,9 @@ public class ComputerCraft Config.turtlesCanPush = Config.config.get( Configuration.CATEGORY_GENERAL, "turtlesCanPush", turtlesCanPush ); Config.turtlesCanPush.setComment( "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so" ); + Config.maxNotesPerTick = Config.config.get( Configuration.CATEGORY_GENERAL, "maxNotesPerTick", maxNotesPerTick ); + Config.maxNotesPerTick.setComment( "Maximum amount of sounds a speaker can play at once" ); + for (Property property : Config.config.getCategory( Configuration.CATEGORY_GENERAL ).getOrderedValues()) { property.setLanguageKey( "gui.computercraft:config." + CaseFormat.LOWER_CAMEL.to( CaseFormat.LOWER_UNDERSCORE, property.getName() ) ); @@ -326,6 +335,8 @@ public class ComputerCraft turtlesObeyBlockProtection = Config.turtlesObeyBlockProtection.getBoolean(); turtlesCanPush = Config.turtlesCanPush.getBoolean(); + maximumFilesOpen = Math.max(1, Config.maximumFilesOpen.getInt()); + Config.config.save(); } @@ -704,7 +715,7 @@ public class ComputerCraft public static Iterable getVanillaPocketUpgrades() { List upgrades = new ArrayList(); for(IPocketUpgrade upgrade : pocketUpgrades.values()) { - if(upgrade instanceof PocketModem) { + if(upgrade instanceof PocketModem || upgrade instanceof PocketSpeaker) { upgrades.add( upgrade ); } } diff --git a/src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java index 790eb8b99..22fdfe893 100644 --- a/src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java @@ -155,6 +155,8 @@ public class CCTurtleProxyClient extends CCTurtleProxyCommon loadModel( event, "advanced_turtle_modem_on_left" ); loadModel( event, "advanced_turtle_modem_off_right" ); loadModel( event, "advanced_turtle_modem_on_right" ); + loadModel( event, "turtle_speaker_upgrade_left" ); + loadModel( event, "turtle_speaker_upgrade_right" ); loadSmartModel( event, "turtle_dynamic", m_turtleSmartItemModel ); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java index 78ce71267..79c19bf60 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java @@ -6,6 +6,7 @@ package dan200.computercraft.shared.peripheral.speaker; +import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.peripheral.IComputerAccess; @@ -21,11 +22,13 @@ public class SpeakerPeripheral implements IPeripheral { private TileSpeaker m_speaker; private long m_clock; private long m_lastPlayTime; + private int m_notesThisTick; public SpeakerPeripheral() { m_clock = 0; m_lastPlayTime = 0; + m_notesThisTick = 0; } public SpeakerPeripheral(TileSpeaker speaker) @@ -34,9 +37,9 @@ public class SpeakerPeripheral implements IPeripheral { m_speaker = speaker; } - public void updateClock() - { + public void update() { m_clock++; + m_notesThisTick = 0; } public World getWorld() @@ -100,7 +103,7 @@ public class SpeakerPeripheral implements IPeripheral { { // playsound case 0: { - return playSound(args); + return playSound(args, false); } // playnote @@ -162,11 +165,15 @@ public class SpeakerPeripheral implements IPeripheral { throw new LuaException("Expected string, number (optional), number (optional)"); } - return playSound(new Object[] {"block.note." + arguments[0], volume, Math.pow(2d, (pitch - 12) / 12d)}); + // If the resource location for noteblock notes changes, this method call will need to be updated + Object[] returnValue = playSound(new Object[] {"block.note." + arguments[0], volume, Math.pow(2d, (pitch - 12) / 12d)}, true); + m_notesThisTick++; + + return returnValue; } - private Object[] playSound(Object[] arguments) throws LuaException + private Object[] playSound(Object[] arguments, boolean isNote) throws LuaException { float volume = 1f; @@ -209,7 +216,7 @@ public class SpeakerPeripheral implements IPeripheral { ResourceLocation resourceName = new ResourceLocation((String) arguments[0]); - if (m_clock - m_lastPlayTime > TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS) + if (m_clock - m_lastPlayTime > TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS || ((m_clock - m_lastPlayTime == 0) && (m_notesThisTick < ComputerCraft.maxNotesPerTick) && isNote)) { if (SoundEvent.REGISTRY.containsKey(resourceName)) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java index 94a2b2243..34d317e3e 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java @@ -26,7 +26,7 @@ public class TileSpeaker extends TilePeripheralBase @Override public synchronized void update() { - m_peripheral.updateClock(); + m_peripheral.update(); } // IPeripheralTile implementation diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java new file mode 100644 index 000000000..534bd7f0c --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java @@ -0,0 +1,87 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.pocket.peripherals; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class PocketSpeaker implements IPocketUpgrade +{ + public PocketSpeaker() + { + } + + @Nonnull + @Override + public ResourceLocation getUpgradeID() + { + return new ResourceLocation( "computercraft", "speaker" ); + } + + @Nonnull + @Override + public String getUnlocalisedAdjective() + { + return "upgrade.computercraft:speaker.adjective"; + } + + @Nullable + @Override + public ItemStack getCraftingItem() + { + return PeripheralItemFactory.create(PeripheralType.Speaker, null, 1); + } + + @Nullable + @Override + public IPeripheral createPeripheral( @Nonnull IPocketAccess access ) + { + return new PocketSpeakerPeripheral(); + } + + @Override + public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) + { + if ( peripheral instanceof PocketSpeakerPeripheral ) + { + Entity entity = access.getEntity(); + + PocketSpeakerPeripheral speaker = (PocketSpeakerPeripheral) peripheral; + + if ( entity instanceof EntityLivingBase) + { + EntityLivingBase player = (EntityLivingBase) entity; + speaker.setLocation( entity.getEntityWorld(), player.posX, player.posY + player.getEyeHeight(), player.posZ ); + } + + else if ( entity != null ) + { + speaker.setLocation( entity.getEntityWorld(), entity.posX, entity.posY, entity.posZ ); + } + speaker.update(); + } + } + + @Override + public boolean onRightClick(@Nonnull World world, @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) + { + return false; + } + + +} diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java new file mode 100644 index 000000000..97bb6df58 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java @@ -0,0 +1,58 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.pocket.peripherals; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class PocketSpeakerPeripheral extends SpeakerPeripheral +{ + private World m_world; + private BlockPos m_position; + + public PocketSpeakerPeripheral() + { + super(); + m_world = null; + m_position = new BlockPos( 0.0, 0.0, 0.0 ); + } + + public void setLocation( World world, double x, double y, double z ) + { + m_position = new BlockPos( x, y, z ); + + if( m_world != world ) + { + m_world = world; + } + } + + @Override + public World getWorld() + { + return m_world; + } + + @Override + public BlockPos getPos() + { + if( m_world != null ) + { + return m_position; + } + return null; + } + + @Override + public boolean equals( IPeripheral other ) + { + // Sufficient because of use case: checking peripherals on individual pocket computers -- there will not be +1 + return other instanceof PocketSpeakerPeripheral; + } +} diff --git a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java index 9751914ce..42d6ebd49 100644 --- a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java +++ b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java @@ -49,6 +49,7 @@ import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory; import dan200.computercraft.shared.pocket.peripherals.PocketModem; +import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker; import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe; import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; @@ -453,6 +454,9 @@ public abstract class ComputerCraftProxyCommon implements IComputerCraftProxy ComputerCraft.PocketUpgrades.advancedModem = new PocketModem( true ); ComputerCraftAPI.registerPocketUpgrade( ComputerCraft.PocketUpgrades.advancedModem ); + ComputerCraft.PocketUpgrades.pocketSpeaker = new PocketSpeaker(); + ComputerCraftAPI.registerPocketUpgrade( ComputerCraft.PocketUpgrades.pocketSpeaker ); + // Wireless Pocket Computer GameRegistry.addRecipe( new PocketComputerUpgradeRecipe() ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java index a83e5f193..923a45db4 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java @@ -24,7 +24,6 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; - import javax.annotation.Nonnull; import javax.vecmath.Matrix4f; @@ -41,6 +40,12 @@ public class TurtleSpeaker implements ITurtleUpgrade m_turtle = turtle; } + @Override + public void update() + { + super.update(); + } + @Override public World getWorld() { @@ -67,9 +72,8 @@ public class TurtleSpeaker implements ITurtleUpgrade } // Members - ResourceLocation m_id; - int m_legacyID; - Peripheral m_peripheral; + private ResourceLocation m_id; + private int m_legacyID; @SideOnly( Side.CLIENT ) private ModelResourceLocation m_leftModel; @@ -77,7 +81,7 @@ public class TurtleSpeaker implements ITurtleUpgrade @SideOnly( Side.CLIENT ) private ModelResourceLocation m_rightModel; - public TurtleSpeaker(ResourceLocation id, int legacyId ) + public TurtleSpeaker(ResourceLocation id, int legacyId) { m_id = id; m_legacyID = legacyId; @@ -119,15 +123,14 @@ public class TurtleSpeaker implements ITurtleUpgrade @Override public IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) { - m_peripheral = new TurtleSpeaker.Peripheral( turtle ); - return m_peripheral; // TODO does this go in constructor? + return new TurtleSpeaker.Peripheral(turtle); } @Nonnull @Override public TurtleCommandResult useTool(@Nonnull ITurtleAccess turtleAccess, @Nonnull TurtleSide turtleSide, @Nonnull TurtleVerb verb, @Nonnull EnumFacing direction) { - return null; + return TurtleCommandResult.failure(); } @SideOnly( Side.CLIENT ) @@ -161,8 +164,12 @@ public class TurtleSpeaker implements ITurtleUpgrade } @Override - public void update(@Nonnull ITurtleAccess turtleAccess, @Nonnull TurtleSide turtleSide) + public void update(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide turtleSide) { - m_peripheral.updateClock(); + if (turtle.getPeripheral(turtleSide) instanceof Peripheral) + { + Peripheral peripheral = (Peripheral) turtle.getPeripheral(turtleSide); + peripheral.update(); + } } } diff --git a/src/main/resources/assets/computercraft/models/block/speaker.json b/src/main/resources/assets/computercraft/models/block/speaker.json index afc4d4e21..288d44523 100644 --- a/src/main/resources/assets/computercraft/models/block/speaker.json +++ b/src/main/resources/assets/computercraft/models/block/speaker.json @@ -1,8 +1,8 @@ { "parent": "block/orientable", "textures": { - "front": "computercraft:blocks/speakerFront", - "side": "computercraft:blocks/speakerSide", - "top": "computercraft:blocks/speakerTop" + "front": "computercraft:blocks/speaker_front", + "side": "computercraft:blocks/speaker_side", + "top": "computercraft:blocks/speaker_top" } } diff --git a/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_left.json b/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_left.json index bfc5c4e3d..d2109d0ec 100644 --- a/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_left.json +++ b/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_left.json @@ -1,6 +1,6 @@ { "parent": "computercraft:block/turtle_upgrade_base_left", "textures": { - "texture": "computercraft:blocks/speakerFront" + "texture": "computercraft:blocks/turtle_speaker_face" } } diff --git a/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_right.json b/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_right.json index 143d681fa..96e67bcc0 100644 --- a/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_right.json +++ b/src/main/resources/assets/computercraft/models/block/turtle_speaker_upgrade_right.json @@ -1,6 +1,6 @@ { "parent": "computercraft:block/turtle_upgrade_base_right", "textures": { - "texture": "computercraft:blocks/speakerFront" + "texture": "computercraft:blocks/turtle_speaker_face" } } diff --git a/src/main/resources/assets/computercraft/textures/blocks/speakerFront.png b/src/main/resources/assets/computercraft/textures/blocks/speaker_front.png similarity index 100% rename from src/main/resources/assets/computercraft/textures/blocks/speakerFront.png rename to src/main/resources/assets/computercraft/textures/blocks/speaker_front.png diff --git a/src/main/resources/assets/computercraft/textures/blocks/speakerSide.png b/src/main/resources/assets/computercraft/textures/blocks/speaker_side.png similarity index 100% rename from src/main/resources/assets/computercraft/textures/blocks/speakerSide.png rename to src/main/resources/assets/computercraft/textures/blocks/speaker_side.png diff --git a/src/main/resources/assets/computercraft/textures/blocks/speakerTop.png b/src/main/resources/assets/computercraft/textures/blocks/speaker_top.png similarity index 100% rename from src/main/resources/assets/computercraft/textures/blocks/speakerTop.png rename to src/main/resources/assets/computercraft/textures/blocks/speaker_top.png diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_speaker_face.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_speaker_face.png new file mode 100644 index 000000000..b115d457c Binary files /dev/null and b/src/main/resources/assets/computercraft/textures/blocks/turtle_speaker_face.png differ