/*
* The MIT License (MIT)
*
* Copyright (c) 2014 Cayde Dixon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.cazzar.mods.jukeboxreloaded.blocks;
import net.cazzar.corelib.lib.InventoryUtils;
import net.cazzar.corelib.lib.SoundSystemHelper;
import net.cazzar.corelib.tile.SyncedTileEntity;
import net.cazzar.corelib.util.ClientUtil;
import net.cazzar.corelib.util.CommonUtil;
import net.cazzar.mods.jukeboxreloaded.client.particles.Particles;
import net.cazzar.mods.jukeboxreloaded.lib.RepeatMode;
import net.cazzar.mods.jukeboxreloaded.network.PacketHandler;
import net.cazzar.mods.jukeboxreloaded.network.packet.*;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemRecord;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.gui.IUpdatePlayerListBox;
import net.minecraft.util.IChatComponent;
import java.util.Random;
//@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers")
public class TileJukebox extends SyncedTileEntity implements IInventory, IUpdatePlayerListBox {//, SimpleComponent {
public ItemStack[] items;
public boolean playing = false;
public int waitTicks = 0;
public float volume = 0.5F;
int metadata;
int recordNumber = 0;
String lastPlayingRecord = "";
//boolean repeat = true;
//boolean repeatAll = false;
boolean shuffle = false;
RepeatMode repeatMode = RepeatMode.ALL;
int tick = 0;
private short facing;
public TileJukebox() {
items = new ItemStack[getSizeInventory()];
}
public TileJukebox(int metadata) {
this();
this.metadata = metadata;
}
/**
* Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot.
*/
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack) {
return itemstack.getItem() instanceof ItemRecord;
}
@Override
public int getField(int id) {
return 0;
}
@Override
public void setField(int id, int value) {
}
@Override
public int getFieldCount() {
return 0;
}
@Override
public void clear() {
}
@Override
public ItemStack decrStackSize(int slot, int amount) {
items[slot].stackSize -= amount;
return items[slot];
}
public int getCurrentRecordNumber() {
return recordNumber;
}
// @Override
// public void getDescriptionPacket() {
// return (new PacketJukeboxDescription(this)).makePacket();
// }
public short getFacing() {
return facing;
}
public void setFacing(short direction) {
facing = direction;
}
@Override
public int getInventoryStackLimit() {
return 1;
}
public int getLastSlotWithItem() {
int i = 0;
for (final ItemStack itemStack : items) {
if (itemStack == null) break;
i++;
}
return i - 1;
}
/**
* @return 0: none <br> 1: all <br> 2: one
*/
public RepeatMode getReplayMode() {
//if (repeat) return 2;
//else if (repeatAll) return 1;
//else return 0;
return repeatMode;
}
@Override
public int getSizeInventory() {
return 12;
}
@Override
public ItemStack getStackInSlot(int slot) {
return items[slot];
}
@Override
public ItemStack getStackInSlotOnClosing(int slot) {
final ItemStack stack = getStackInSlot(slot);
if (stack != null) setInventorySlotContents(slot, null);
return stack;
}
public boolean isPlayingRecord() {
if (!worldObj.isRemote && CommonUtil.isServer()) return playing;
return SoundSystemHelper.isPlaying(getIdentifier());
}
@Override
public boolean isUseableByPlayer(EntityPlayer entityplayer) {
return true;
}
@Override
public void openInventory(EntityPlayer player) {
}
@Override
public void closeInventory(EntityPlayer player) {
}
public void markForUpdate() {
worldObj.markBlockForUpdate(pos);
markDirty();
}
public void nextRecord() {
if (recordNumber++ >= getSizeInventory() - 1) recordNumber = 0;
}
public void playSelectedRecord() {
if (getStackInSlot(recordNumber) == null) return;
if (worldObj.isRemote) {
PacketHandler.INSTANCE.sendToServer(new ClientPlayRecord(this));
return;
}
lastPlayingRecord = ((ItemRecord) getStackInSlot(recordNumber).getItem()).recordName;
playing = true;
waitTicks = 20;
PacketHandler.INSTANCE.sendToAll(new ServerPlayRecord(this));
}
public void previousRecord() {
if (recordNumber == 0) recordNumber = getSizeInventory() - 1;
else recordNumber--;
}
@Override
public void readFromNBT(NBTTagCompound tag) {
super.readFromNBT(tag);
recordNumber = tag.getInteger("recordNumber");
facing = tag.getShort("facing");
shuffle = tag.getBoolean("shuffle");
setRepeatMode(RepeatMode.get(tag.getInteger("rptMode")));
volume = tag.getFloat("volume");
InventoryUtils.readItemStacksFromTag(items, tag.getTagList("inventory", 10));
}
public void resetPlayingRecord() {
recordNumber = 0;
}
@Override
public void setInventorySlotContents(int slot, ItemStack itemstack) {
items[slot] = itemstack;
if (recordNumber == slot && isPlayingRecord() && itemstack == null)
playSelectedRecord();
}
@Override
public String getName() {
return null;
}
@Override
public boolean hasCustomName() {
return false;
}
@Override
public IChatComponent getDisplayName() {
return null;
}
public void setPlaying(boolean playing) {
this.playing = playing;
}
public void setRecordPlaying(int recordNumber) {
final int oldRecord = this.recordNumber;
this.recordNumber = recordNumber;
if (isPlayingRecord() && oldRecord != recordNumber)
playSelectedRecord();
markForUpdate();
}
/**
* @param mode 0: none <br> 1: all <br> 2: one
*/
public void setRepeatMode(RepeatMode mode) {
repeatMode = mode;
}
public void setShuffle(boolean shuffle) {
this.shuffle = shuffle;
}
public boolean shuffleEnabled() {
return shuffle;
}
public void stopPlayingRecord() {
playing = false;
if (CommonUtil.isServer())
PacketHandler.INSTANCE.sendToAll(new ServerAction(ClientAction.Action.STOP, this));
else PacketHandler.INSTANCE.sendToServer(new ClientAction(ClientAction.Action.STOP, this));
}
@Override
public void update() {
if (!ClientUtil.isClient()) return;
tick++;
final Random random = worldObj.rand;
if (tick % 5 == 0 && random.nextBoolean())
if (isPlayingRecord()) {
SoundSystemHelper.getSoundSystem().setVolume(getIdentifier(), volume * ClientUtil.mc().gameSettings.getSoundLevel(SoundCategory.RECORDS));
SoundSystemHelper.stop("bgMusic");
Particles particles = Particles.values()[random.nextInt(Particles.values().length)];
particles.spawn(pos.getX() + random.nextDouble(), pos.getY() + 1.2D, pos.getZ() + random.nextDouble());
}
if (tick % 10 != 0) return;
if (waitTicks-- >= 0) return;
waitTicks = 0;
if (!SoundSystemHelper.isSoundEnabled()) return; // Thanks to
// alex
// streaming is only used on the client for playing in the jukebox..
if (!isPlayingRecord()) {
final boolean wasPlaying = playing;
if (!wasPlaying) return;
// if repeating
if (repeatMode == RepeatMode.ONE && !shuffle) playSelectedRecord();
else if (repeatMode == RepeatMode.ALL && !shuffle) {
nextRecord();
if (recordNumber == getLastSlotWithItem() + 1)
resetPlayingRecord();
playSelectedRecord();
} else if (!shuffle) {
stopPlayingRecord();
resetPlayingRecord();
}
// send tile information to the server to update the other clients
if (shuffle && repeatMode != RepeatMode.ONE) {
PacketHandler.INSTANCE.sendToServer(new ClientShuffle(this));
}
markForUpdate();
}
}
@Override
public void writeToNBT(NBTTagCompound tag) {
super.writeToNBT(tag);
tag.setInteger("recordNumber", recordNumber);
tag.setShort("facing", facing);
tag.setInteger("rptMode", getReplayMode().ordinal());
tag.setBoolean("shuffle", shuffle);
tag.setFloat("volume", volume);
tag.setTag("inventory", InventoryUtils.writeItemStacksToTag(items));
}
public String getIdentifier() {
if (getStackInSlot(getCurrentRecordNumber()) == null) return "";
return SoundSystemHelper.getIdentifierForRecord(((ItemRecord) getStackInSlot(getCurrentRecordNumber()).getItem()), pos.getX(), pos.getY(), pos.getZ());
}
/*@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] getRecordName(Context context, Arguments args) {
String s = ((ItemRecord) getStackInSlot(recordNumber).getItem()).recordName;
if (FMLCommonHandler.instance().getEffectiveSide().isClient())
s = ((ItemRecord) getStackInSlot(recordNumber).getItem()).recordName;
s = s.replace("cazzar:kokoro", "Kagamine Rin - Kokoro")
.replace("cazzar:love_is_war", "Hatsune Miku - Love Is war")
.replace("cazzar:shibuya", "BECCA - SHIBUYA (Original)")
.replace("cazzar:spica", "Hatsune Miku - SPiCa")
.replace("cazzar:suki_daisuki", "Kagamine Rin - I Like You, I Love You")
.replace("cazzar:we_are_popcandy", "Hatsune Miku - We are POPCANDY!");
return new String[]{s};
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] isPlaying(Context context, Arguments args) {
return new Object[]{isPlayingRecord()};
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] play(Context context, Arguments args) {
playSelectedRecord();
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] stop(Context context, Arguments args) {
stopPlayingRecord();
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] next(Context context, Arguments args) {
boolean wasPlaying = isPlayingRecord();
if (wasPlaying) stopPlayingRecord();
if (shuffleEnabled()) {
final Random random = new Random();
if (getLastSlotWithItem() <= 0) return null;
final int nextDisk = random.nextInt(getLastSlotWithItem());
if (getCurrentRecordNumber() != nextDisk)
setRecordPlaying(nextDisk);
}
nextRecord();
if (wasPlaying) playSelectedRecord();
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] previous(Context context, Arguments args) {
boolean wasPlaying = isPlayingRecord();
if (wasPlaying) stopPlayingRecord();
previousRecord();
if (wasPlaying) playSelectedRecord();
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] setRepeatOne(Context context, Arguments args) {
repeatMode = RepeatMode.ONE;
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] setRepeatNone(Context context, Arguments args) {
repeatMode = RepeatMode.OFF;
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] setRepeatAll(Context context, Arguments args) {
repeatMode = RepeatMode.ALL;
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] enableShuffle(Context context, Arguments args) {
shuffle = true;
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] disableShuffle(Context context, Arguments args) {
shuffle = false;
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] toggleShuffle(Context context, Arguments args) {
shuffle = !shuffle;
markForUpdate();
return null;
}
@Optional.Method(modid = "OpenComputers")
@Callback
public Object[] setVolume(Context context, Arguments args) {
int vol = args.checkInteger(1);
if (vol >= 1f)
volume = 1f;
else if (vol <= 0f) volume = 0f;
else volume = vol;
markForUpdate();
return new Object[]{volume};
}*/
@Override
public void addExtraNBTToPacket(NBTTagCompound tag) {
tag.setBoolean("playing", playing);
}
@Override
public void readExtraNBTFromPacket(NBTTagCompound tag) {
if (tag.getBoolean("playing") && !playing)
playSelectedRecord();
}
/*@Optional.Method(modid = "OpenComputers")
@Override
public String getComponentName() {
return "jukebox";
}*/
}