From f052016de5bbabb1863882a7cb666a18a5907874 Mon Sep 17 00:00:00 2001 From: Goodbird Date: Sun, 21 Jan 2024 10:57:35 +0300 Subject: [PATCH] Added scripted block and its tile --- .../noppes/npcs/blocks/BlockScripted.java | 214 +++++++ .../npcs/blocks/tiles/TileScripted.java | 526 ++++++++++++++++++ 2 files changed, 740 insertions(+) create mode 100644 src/main/java/noppes/npcs/blocks/BlockScripted.java create mode 100644 src/main/java/noppes/npcs/blocks/tiles/TileScripted.java diff --git a/src/main/java/noppes/npcs/blocks/BlockScripted.java b/src/main/java/noppes/npcs/blocks/BlockScripted.java new file mode 100644 index 000000000..a2d2e6c31 --- /dev/null +++ b/src/main/java/noppes/npcs/blocks/BlockScripted.java @@ -0,0 +1,214 @@ +package noppes.npcs.blocks; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.Explosion; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import noppes.npcs.CustomItems; +import noppes.npcs.EventHooks; +import noppes.npcs.NoppesUtilServer; +import noppes.npcs.blocks.tiles.TileScripted; +import noppes.npcs.constants.EnumGuiType; + +import java.util.Random; + +public class BlockScripted extends BlockContainer { + public static final AxisAlignedBB AABB = AxisAlignedBB.getBoundingBox(0.001f, 0.001f, 0.001f, 0.998f, 0.998f, 0.998f); + public static final AxisAlignedBB AABB_EMPTY = AxisAlignedBB.getBoundingBox(0, 0, 0, 0, 0, 0); + + public BlockScripted() { + super(Material.rock); + setStepSound(soundTypeStone); + } + + @Override + public TileEntity createNewTileEntity(World worldIn, int meta) { + return new TileScripted(); + } + + @Override + public AxisAlignedBB getSelectedBoundingBoxFromPool(World world, int x, int y, int z) { + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + if (tile != null && tile.isPassible) + return AABB_EMPTY; + return AABB; + } + + @Override + public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) { + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + if (tile != null && tile.isPassible) + return AABB_EMPTY; + return AABB; + } + + @Override + public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { + if (world.isRemote) + return true; + ItemStack currentItem = player.inventory.getCurrentItem(); + if (currentItem != null && (currentItem.getItem() == CustomItems.wand || currentItem.getItem() == CustomItems.scripter)) { + NoppesUtilServer.sendOpenGui(player, EnumGuiType.ScriptBlock, null, x, y, z); + return true; + } + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + return !EventHooks.onScriptBlockInteract(tile, player, side, hitX, hitY, hitZ); + } + + @Override + public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entity, ItemStack itemStack) { + if (entity instanceof EntityPlayer && !world.isRemote) { + NoppesUtilServer.sendOpenGui((EntityPlayer) entity, EnumGuiType.ScriptBlock, null, x, y, z); + } + } + + @Override + public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entityIn) { + if (world.isRemote) + return; + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + EventHooks.onScriptBlockCollide(tile, entityIn); + } + + @Override + public void fillWithRain(World world, int x, int y, int z) { + if (world.isRemote) + return; + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + EventHooks.onScriptBlockRainFill(tile); + } + + + @Override + public void onFallenUpon(World world, int x, int y, int z, Entity entity, float fallDistance) { + if (world.isRemote) + return; + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + fallDistance = EventHooks.onScriptBlockFallenUpon(tile, entity, fallDistance); + super.onFallenUpon(world, x, y, z, entity, fallDistance); + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean isNormalCube() { + return false; + } + + @Override + public void onBlockClicked(World world, int x, int y, int z, EntityPlayer player) { + if (world.isRemote) + return; + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + EventHooks.onScriptBlockClicked(tile, player); + } + + @Override + public void breakBlock(World world, int x, int y, int z, Block block, int metadata) { + if (!world.isRemote) { + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + EventHooks.onScriptBlockBreak(tile); + } + super.breakBlock(world, x, y, z, block, metadata); + } + + @Override + public boolean removedByPlayer(World world, EntityPlayer player, int x, int y, int z, boolean willHarvest) { + if (!world.isRemote) { + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + if (EventHooks.onScriptBlockHarvest(tile, player)) + return false; + } + return super.removedByPlayer(world, player, x, y, z, willHarvest); + } + + @Override + public Item getItemDropped(int i, Random rand, int fortune) { + return null; + } + + @Override + public void onBlockExploded(World world, int x, int y, int z, Explosion explosion) { + if (!world.isRemote) { + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + if (EventHooks.onScriptBlockExploded(tile)) + return; + } + super.onBlockExploded(world, x, y, z, explosion); + } + + @Override + public boolean canProvidePower() { + return true; + } + + + @Override + public int isProvidingWeakPower(IBlockAccess worldIn, int x, int y, int z, int side) { + return this.isProvidingStrongPower(worldIn, x, y, z, side); + } + + @Override + public int isProvidingStrongPower(IBlockAccess world, int x, int y, int z, int side) { + return ((TileScripted) world.getTileEntity(x, y, z)).activePowering; + } + + @Override + public boolean isLadder(IBlockAccess world, int x, int y, int z, EntityLivingBase entity) { + return ((TileScripted) world.getTileEntity(x, y, z)).isLadder; + } + + @Override + public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z) { + return true; + } + + @Override + public float getBlockHardness(World world, int x, int y, int z) { + return ((TileScripted) world.getTileEntity(x, y, z)).blockHardness; + } + + @Override + public int getLightValue(IBlockAccess world, int x, int y, int z) { + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + if (tile == null) + return 0; + return tile.lightValue; + } + + @Override + public float getExplosionResistance(Entity par1Entity, World world, int x, int y, int z, double explosionX, double explosionY, double explosionZ) { + return ((TileScripted) world.getTileEntity(x, y, z)).blockResistance; + } + + @Override + public void onNeighborChange(IBlockAccess world, int x, int y, int z, int tileX, int tileY, int tileZ) { + TileScripted tile = (TileScripted) world.getTileEntity(x, y, z); + EventHooks.onScriptBlockNeighborChanged(tile, tileX, tileY, tileZ); + + int power = 0; + for (EnumFacing enumfacing : EnumFacing.values()) { + int p = world.isBlockProvidingPowerTo(x + enumfacing.getFrontOffsetX(), + y + enumfacing.getFrontOffsetZ(), z + enumfacing.getFrontOffsetZ(), enumfacing.ordinal()); + if (p > power) + power = p; + } + if (tile.prevPower != power && tile.powering <= 0) { + tile.newPower = power; + } + } +} diff --git a/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java new file mode 100644 index 000000000..b03d03e30 --- /dev/null +++ b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java @@ -0,0 +1,526 @@ +package noppes.npcs.blocks.tiles; + +import cpw.mods.fml.common.eventhandler.Event; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.block.Block; +import net.minecraft.client.renderer.texture.ITickable; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S35PacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.EnumSkyBlock; +import net.minecraft.world.World; +import noppes.npcs.*; +import noppes.npcs.api.IBlock; +import noppes.npcs.api.block.ITextPlane; +import noppes.npcs.constants.EnumScriptType; +import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.controllers.ScriptController; +import noppes.npcs.controllers.data.INpcScriptHandler; +import noppes.npcs.controllers.data.IScriptBlockHandler; +import noppes.npcs.entity.data.DataTimers; +import noppes.npcs.scripted.BlockScriptedWrapper; +import noppes.npcs.util.ValueUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +public class TileScripted extends TileEntity implements IScriptBlockHandler { + public List scripts = new ArrayList<>(); + + public String scriptLanguage = "ECMAScript"; + public boolean enabled = false; + + private IBlock blockDummy = null; + public DataTimers timers = new DataTimers(this); + + public long lastInited = -1; + + private short ticksExisted = 0; + + public ItemStack itemModel = new ItemStack(CustomItems.scripted); + public Block blockModel = null; + + public boolean needsClientUpdate = false; + + public int powering = 0; + public int activePowering = 0; + public int newPower = 0; //used for block redstone event + public int prevPower = 0; //used for block redstone event + + public boolean isPassible = false; + public boolean isLadder = false; + public int lightValue = 0; + + public float blockHardness = 5; + public float blockResistance = 10; + + public int rotationX = 0, rotationY = 0, rotationZ = 0; + public float scaleX = 1, scaleY = 1, scaleZ = 1; + + public TileEntity renderTile; + public boolean renderTileErrored = true; + public ITickable renderTileUpdate = null; + + public TextPlane text1 = new TextPlane(); + public TextPlane text2 = new TextPlane(); + public TextPlane text3 = new TextPlane(); + public TextPlane text4 = new TextPlane(); + public TextPlane text5 = new TextPlane(); + public TextPlane text6 = new TextPlane(); + + public IBlock getBlock(){ + if(blockDummy == null) + blockDummy = new BlockScriptedWrapper(worldObj, this.getBlockType(), xCoord,yCoord,zCoord); + return blockDummy; + } + + @Override + public void readFromNBT(NBTTagCompound compound){ + super.readFromNBT(compound); + setNBT(compound); + setDisplayNBT(compound); + timers.readFromNBT(compound); + } + + public void setNBT(NBTTagCompound compound){ + scripts = NBTTags.GetScriptOld(compound.getTagList("Scripts", 10), this); + scriptLanguage = compound.getString("ScriptLanguage"); + enabled = compound.getBoolean("ScriptEnabled"); + activePowering = powering = compound.getInteger("BlockPowering"); + prevPower = compound.getInteger("BlockPrevPower"); + + if(compound.hasKey("BlockHardness")){ + blockHardness = compound.getFloat("BlockHardness"); + blockResistance = compound.getFloat("BlockResistance"); + } + + } + public void setDisplayNBT(NBTTagCompound compound){ + itemModel = ItemStack.loadItemStackFromNBT(compound.getCompoundTag("ScriptBlockModel")); + if(itemModel.stackSize == 0) + itemModel = new ItemStack(Item.getItemFromBlock(CustomItems.scripted)); + if(compound.hasKey("ScriptBlockModelBlock")) + blockModel = Block.getBlockFromName(compound.getString("ScriptBlockModelBlock")); + renderTileUpdate = null; + renderTile = null; + renderTileErrored = false; + + lightValue = compound.getInteger("LightValue"); + isLadder = compound.getBoolean("IsLadder"); + isPassible = compound.getBoolean("IsPassible"); + + rotationX = compound.getInteger("RotationX"); + rotationY = compound.getInteger("RotationY"); + rotationZ = compound.getInteger("RotationZ"); + + scaleX = compound.getFloat("ScaleX"); + scaleY = compound.getFloat("ScaleY"); + scaleZ = compound.getFloat("ScaleZ"); + + if(scaleX <= 0) + scaleX = 1; + if(scaleY <= 0) + scaleY = 1; + if(scaleZ <= 0) + scaleZ = 1; + + if(compound.hasKey("Text3")) { + text1.setNBT(compound.getCompoundTag("Text1")); + text2.setNBT(compound.getCompoundTag("Text2")); + text3.setNBT(compound.getCompoundTag("Text3")); + text4.setNBT(compound.getCompoundTag("Text4")); + text5.setNBT(compound.getCompoundTag("Text5")); + text6.setNBT(compound.getCompoundTag("Text6")); + } + } + + @Override + public void writeToNBT(NBTTagCompound compound){ + getNBT(compound); + getDisplayNBT(compound); + timers.writeToNBT(compound); + } + + public NBTTagCompound getNBT(NBTTagCompound compound){ + compound.setTag("Scripts", NBTTags.NBTScript(scripts)); + compound.setString("ScriptLanguage", scriptLanguage); + compound.setBoolean("ScriptEnabled", enabled); + compound.setInteger("BlockPowering", powering); + compound.setInteger("BlockPrevPower", prevPower); + compound.setFloat("BlockHardness", blockHardness); + compound.setFloat("BlockResistance", blockResistance); + return compound; + } + + public void getDisplayNBT(NBTTagCompound compound){ + NBTTagCompound itemcompound = new NBTTagCompound(); + itemModel.writeToNBT(itemcompound); + if(blockModel != null){ + compound.setString("ScriptBlockModelBlock", Block.blockRegistry.getNameForObject(blockModel)); + } + compound.setTag("ScriptBlockModel", itemcompound); + compound.setInteger("LightValue", lightValue); + compound.setBoolean("IsLadder", isLadder); + compound.setBoolean("IsPassible", isPassible); + + compound.setInteger("RotationX", rotationX); + compound.setInteger("RotationY", rotationY); + compound.setInteger("RotationZ", rotationZ); + + compound.setFloat("ScaleX", scaleX); + compound.setFloat("ScaleY", scaleY); + compound.setFloat("ScaleZ", scaleZ); + + compound.setTag("Text1", text1.getNBT()); + compound.setTag("Text2", text2.getNBT()); + compound.setTag("Text3", text3.getNBT()); + compound.setTag("Text4", text4.getNBT()); + compound.setTag("Text5", text5.getNBT()); + compound.setTag("Text6", text6.getNBT()); + + } + + private boolean isEnabled() { + return enabled && ScriptController.HasStart && !worldObj.isRemote; + } + + @Override + public void updateEntity() { + if(renderTileUpdate != null){ + try{ + renderTileUpdate.tick(); + } + catch(Exception e){ + renderTileUpdate = null; + } + } + ticksExisted++; + if (prevPower != newPower && powering <= 0){ + EventHooks.onScriptBlockRedstonePower(this, prevPower, newPower); + prevPower = newPower; + } + + timers.update(); + if(ticksExisted >= 10){ + EventHooks.onScriptBlockUpdate(this); + ticksExisted = 0; + if(needsClientUpdate){ + markDirty(); + worldObj.notifyBlocksOfNeighborChange(xCoord,yCoord,zCoord,getBlockType(),3); + needsClientUpdate = false; + } + } + } + + @Override + public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { + handleUpdateTag(pkt.func_148857_g()); + } + + public void handleUpdateTag(NBTTagCompound tag){ + int light = lightValue; + setDisplayNBT(tag); + if(light != lightValue) + checkLight(worldObj,xCoord,yCoord,zCoord); + } + + public boolean checkLight(World world, int x, int y, int z) + { + boolean flag = false; + + if (!world.provider.hasNoSky) + { + flag |= world.updateLightByType(EnumSkyBlock.Sky, x,y,z); + } + + flag = flag | world.updateLightByType(EnumSkyBlock.Block, x,y,z); + return flag; + } + + @Override + public Packet getDescriptionPacket() { + return new S35PacketUpdateTileEntity(xCoord,yCoord,zCoord, 0, getUpdateTag()); + } + + public NBTTagCompound getUpdateTag(){ + NBTTagCompound compound = new NBTTagCompound(); + compound.setInteger("x", xCoord); + compound.setInteger("y", yCoord); + compound.setInteger("z", zCoord); + getDisplayNBT(compound); + return compound; + } + + public void setItemModel(ItemStack item, Block b) { + if(item == null || item.stackSize==0){ + item = new ItemStack(CustomItems.scripted); + } + if(NoppesUtilPlayer.compareItems(item, itemModel, false, false) && b != blockModel) + return; + + itemModel = item; + blockModel = b; + needsClientUpdate = true; + } + + public void setLightValue(int value){ + if(value == lightValue) + return; + lightValue = ValueUtil.clamp(value, 0, 15); + needsClientUpdate = true; + } + + public void setRedstonePower(int strength){ + if(powering == strength) + return; + //using activePowering to prevent the RedstonePower script event from going crazy + prevPower = activePowering = ValueUtil.clamp(strength, 0, 15); + worldObj.notifyBlockChange(xCoord,yCoord,zCoord, getBlockType()); + powering = activePowering; + } + + public void setScale(float x, float y, float z){ + if(scaleX == x && scaleY == y && scaleZ == z) + return; + scaleX = ValueUtil.clamp(x, 0, 10); + scaleY = ValueUtil.clamp(y, 0, 10); + scaleZ = ValueUtil.clamp(z, 0, 10); + needsClientUpdate = true; + } + + public void setRotation(int x, int y, int z){ + if(rotationX == x && rotationY == y && rotationZ == z) + return; + rotationX = ValueUtil.clamp(x, 0, 359); + rotationY = ValueUtil.clamp(y, 0, 359); + rotationZ = ValueUtil.clamp(z, 0, 359); + needsClientUpdate = true; + } + + @Override + public void callScript(EnumScriptType type, Event event) { + if(!isEnabled()) + return; + if(ScriptController.Instance.lastLoaded > lastInited){ + lastInited = ScriptController.Instance.lastLoaded; + if(type != EnumScriptType.INIT) + EventHooks.onScriptBlockInit(this); + } + + for(ScriptContainer script : scripts){ + script.run(type, event); + } + } + + @Override + public void callScript(String hookName, Event event) { + callScript(EnumScriptType.valueOf(hookName),event); + } + + @Override + public boolean isClient() { + return worldObj.isRemote; + } + + @Override + public boolean getEnabled() { + return enabled; + } + + @Override + public void setEnabled(boolean bo) { + enabled = bo; + } + + @Override + public String noticeString() { + return "x: "+xCoord+", y: "+yCoord+", z: "+zCoord; + } + + @Override + public String getLanguage() { + return scriptLanguage; + } + + @Override + public void setLanguage(String lang) { + scriptLanguage = lang; + } + + @Override + public void setScripts(List list) { + scripts = list; + } + + @Override + public List getScripts() { + return scripts; + } + + @Override + public Map getConsoleText(){ + Map map = new TreeMap<>(); + int tab = 0; + for(ScriptContainer script : getScripts()){ + tab++; + for(Entry entry : script.console.entrySet()){ + map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); + } + } + return map; + } + + @Override + public void clearConsole() { + for(ScriptContainer script : getScripts()){ + script.console.clear(); + } + } + + @SideOnly(Side.CLIENT) + @Override + public AxisAlignedBB getRenderBoundingBox(){ + return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) + .offset(xCoord,yCoord,zCoord); + } + + public class TextPlane implements ITextPlane { + public boolean textHasChanged = true; + public TextBlock textBlock; + + public String text = ""; + public int rotationX = 0, rotationY = 0, rotationZ = 0; + public float offsetX = 0, offsetY = 0f, offsetZ = 0.5f; + public float scale = 1; + + @Override + public String getText() { + return text; + } + @Override + public void setText(String text) { + if(this.text.equals(text)) + return; + this.text = text; + textHasChanged = true; + needsClientUpdate = true; + } + @Override + public int getRotationX() { + return rotationX; + } + @Override + public int getRotationY() { + return rotationY; + } + @Override + public int getRotationZ() { + return rotationZ; + } + @Override + public void setRotationX(int x) { + x = ValueUtil.clamp(x % 360, 0, 359); + if(rotationX == x) + return; + rotationX = x; + needsClientUpdate = true; + } + @Override + public void setRotationY(int y) { + y = ValueUtil.clamp(y % 360, 0, 359); + if(rotationY == y) + return; + rotationY = y; + needsClientUpdate = true; + } + @Override + public void setRotationZ(int z) { + z = ValueUtil.clamp(z % 360, 0, 359); + if(rotationZ == z) + return; + rotationZ = z; + needsClientUpdate = true; + } + @Override + public float getOffsetX() { + return offsetX; + } + @Override + public float getOffsetY() { + return offsetY; + } + @Override + public float getOffsetZ() { + return offsetZ; + } + @Override + public void setOffsetX(float x) { + x = ValueUtil.clamp(x, -1, 1); + if(offsetX == x) + return; + offsetX = x; + needsClientUpdate = true; + } + @Override + public void setOffsetY(float y) { + y = ValueUtil.clamp(y, -1, 1); + if(offsetY == y) + return; + offsetY = y; + needsClientUpdate = true; + } + @Override + public void setOffsetZ(float z) { + z = ValueUtil.clamp(z, -1, 1); + if(offsetZ == z) + return; + System.out.println(rotationZ); + offsetZ = z; + needsClientUpdate = true; + } + @Override + public float getScale() { + return scale; + } + @Override + public void setScale(float scale) { + if(this.scale == scale) + return; + this.scale = scale; + needsClientUpdate = true; + } + + public NBTTagCompound getNBT() { + NBTTagCompound compound = new NBTTagCompound(); + compound.setString("Text", text); + compound.setInteger("RotationX", rotationX); + compound.setInteger("RotationY", rotationY); + compound.setInteger("RotationZ", rotationZ); + compound.setFloat("OffsetX", offsetX); + compound.setFloat("OffsetY", offsetY); + compound.setFloat("OffsetZ", offsetZ); + compound.setFloat("Scale", scale); + return compound; + } + + public void setNBT(NBTTagCompound compound) { + setText(compound.getString("Text")); + rotationX = compound.getInteger("RotationX"); + rotationY = compound.getInteger("RotationY"); + rotationZ = compound.getInteger("RotationZ"); + offsetX = compound.getFloat("OffsetX"); + offsetY = compound.getFloat("OffsetY"); + offsetZ = compound.getFloat("OffsetZ"); + scale = compound.getFloat("Scale"); + } + } +}