So I tried to implement this myself. Here's what I did:
EnchantmentHelper.java
public static boolean[] enchantBlocks = new boolean[4096];
public static void setBlock(int par1, boolean par2)
{
enchantBlocks[par1] = par2;
}
public static boolean isEnchantmentBlock(int par1)
{
if (enchantBlocks[par1]||par1 == Block.bookShelf.blockID)
{
return true;
}
return false;
}
ContainerEnchantment.java
public void onCraftMatrixChanged(IInventory par1IInventory)
{
if (par1IInventory == this.tableInventory)
{
ItemStack var2 = par1IInventory.getStackInSlot(0);
int var3;
if (var2 != null && var2.isItemEnchantable())
{
this.nameSeed = this.rand.nextLong();
if (!this.worldPointer.isRemote)
{
var3 = 0;
int var4;
for (var4 = -1; var4 <= 1; ++var4)
{
for (int var5 = -1; var5 <= 1; ++var5)
{
if ((var4 != 0 || var5 != 0) && this.worldPointer.isAirBlock(this.posX + var5, this.posY, this.posZ + var4) &&
this.worldPointer.isAirBlock(this.posX + var5, this.posY + 1, this.posZ + var4))
{
if (EnchantmentHelper.isEnchantmentBlock(this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY, this.posZ + var4 * 2)))
{
++var3;
}
if (EnchantmentHelper.isEnchantmentBlock(this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY + 1, this.posZ + var4 * 2)))
{
++var3;
}
if (var5 != 0 && var4 != 0)
{
if (EnchantmentHelper.isEnchantmentBlock(this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY, this.posZ + var4)))
{
++var3;
}
if (EnchantmentHelper.isEnchantmentBlock(this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY + 1, this.posZ + var4)))
{
++var3;
}
if (EnchantmentHelper.isEnchantmentBlock(this.worldPointer.getBlockId(this.posX + var5, this.posY, this.posZ + var4 * 2)))
{
++var3;
}
if (EnchantmentHelper.isEnchantmentBlock(this.worldPointer.getBlockId(this.posX + var5, this.posY + 1, this.posZ + var4 * 2)))
{
++var3;
}
}
}
}
}
for (var4 = 0; var4 < 3; ++var4)
{
this.enchantLevels[var4] = EnchantmentHelper.calcItemStackEnchantability(this.rand, var4, var3, var2);
}
this.updateCraftingResults();
}
}
else
{
for (var3 = 0; var3 < 3; ++var3)
{
this.enchantLevels[var3] = 0;
}
}
}
}
BlockEnchantmentTable.java
public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
{
super.randomDisplayTick(par1World, par2, par3, par4, par5Random);
for (int var6 = par2 - 2; var6 <= par2 + 2; ++var6)
{
for (int var7 = par4 - 2; var7 <= par4 + 2; ++var7)
{
if (var6 > par2 - 2 && var6 < par2 + 2 && var7 == par4 - 1)
{
var7 = par4 + 2;
}
if (par5Random.nextInt(16) == 0)
{
for (int var8 = par3; var8 <= par3 + 1; ++var8)
{
if (EnchantmentHelper.isEnchantmentBlock(par1World.getBlockId(var6, var8, var7)))
{
if (!par1World.isAirBlock((var6 - par2) / 2 + par2, var8, (var7 - par4) / 2 + par4))
{
break;
}
par1World.spawnParticle("enchantmenttable", (double)par2 + 0.5D, (double)par3 + 2.0D, (double)par4 + 0.5D,
(double)((float)(var6 - par2) + par5Random.nextFloat()) - 0.5D, (double)((float)(var8 - par3) - par5Random.nextFloat() - 1.0F),
(double)((float)(var7 - par4) + par5Random.nextFloat()) - 0.5D);
}
}
}
}
}
}
Though I don't know if ContainerEnchantment is the best place to put those hooks...