diff --git a/patches/minecraft/net/minecraft/client/multiplayer/WorldClient.java.patch b/patches/minecraft/net/minecraft/client/multiplayer/WorldClient.java.patch index 83f738dc7c..b2931d8d34 100644 --- a/patches/minecraft/net/minecraft/client/multiplayer/WorldClient.java.patch +++ b/patches/minecraft/net/minecraft/client/multiplayer/WorldClient.java.patch @@ -1,6 +1,6 @@ --- ../src-base/minecraft/net/minecraft/client/multiplayer/WorldClient.java +++ ../src-work/minecraft/net/minecraft/client/multiplayer/WorldClient.java -@@ -60,17 +60,18 @@ +@@ -60,17 +60,19 @@ public WorldClient(NetHandlerPlayClient p_i45063_1_, WorldSettings p_i45063_2_, int p_i45063_3_, EnumDifficulty p_i45063_4_, Profiler p_i45063_5_) { @@ -17,6 +17,7 @@ this.field_72988_C = new SaveDataMemoryStorage(); this.func_72966_v(); this.func_72947_a(); ++ this.initCapabilities(); + net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(this)); } diff --git a/patches/minecraft/net/minecraft/world/World.java.patch b/patches/minecraft/net/minecraft/world/World.java.patch index 3367560896..ac3bbc4536 100644 --- a/patches/minecraft/net/minecraft/world/World.java.patch +++ b/patches/minecraft/net/minecraft/world/World.java.patch @@ -1,8 +1,11 @@ --- ../src-base/minecraft/net/minecraft/world/World.java +++ ../src-work/minecraft/net/minecraft/world/World.java -@@ -61,6 +61,13 @@ +@@ -59,8 +59,15 @@ + import net.minecraftforge.fml.relauncher.Side; + import net.minecraftforge.fml.relauncher.SideOnly; - public abstract class World implements IBlockAccess +-public abstract class World implements IBlockAccess ++public abstract class World implements IBlockAccess, net.minecraftforge.common.capabilities.ICapabilityProvider { + /** + * Used in the getEntitiesWithinAABB functions to expand the search area for entities. @@ -14,18 +17,20 @@ private int field_181546_a = 63; protected boolean field_72999_e; public final List field_72996_f = Lists.newArrayList(); -@@ -102,6 +109,10 @@ +@@ -102,6 +109,12 @@ private final WorldBorder field_175728_M; int[] field_72994_J; + public boolean restoringBlockSnapshots = false; + public boolean captureBlockSnapshots = false; + public java.util.ArrayList capturedBlockSnapshots = new java.util.ArrayList(); ++ private net.minecraftforge.common.capabilities.CapabilityDispatcher capabilities; ++ private net.minecraftforge.common.util.WorldCapabilityData capabilityData; + protected World(ISaveHandler p_i45749_1_, WorldInfo p_i45749_2_, WorldProvider p_i45749_3_, Profiler p_i45749_4_, boolean p_i45749_5_) { this.field_73021_x = Lists.newArrayList(new IWorldEventListener[] {this.field_184152_t}); -@@ -116,6 +127,7 @@ +@@ -116,6 +129,7 @@ this.field_73011_w = p_i45749_3_; this.field_72995_K = p_i45749_5_; this.field_175728_M = p_i45749_3_.func_177501_r(); @@ -33,7 +38,7 @@ } public World func_175643_b() -@@ -125,6 +137,11 @@ +@@ -125,6 +139,11 @@ public Biome func_180494_b(final BlockPos p_180494_1_) { @@ -45,7 +50,7 @@ if (this.func_175667_e(p_180494_1_)) { Chunk chunk = this.func_175726_f(p_180494_1_); -@@ -201,7 +218,7 @@ +@@ -201,7 +220,7 @@ public boolean func_175623_d(BlockPos p_175623_1_) { @@ -54,7 +59,7 @@ } public boolean func_175667_e(BlockPos p_175667_1_) -@@ -298,23 +315,49 @@ +@@ -298,23 +317,49 @@ { Chunk chunk = this.func_175726_f(p_180501_1_); Block block = p_180501_2_.func_177230_c(); @@ -106,7 +111,7 @@ this.func_184138_a(p_180501_1_, iblockstate, p_180501_2_, p_180501_3_); } -@@ -324,11 +367,9 @@ +@@ -324,11 +369,9 @@ if (p_180501_2_.func_185912_n()) { @@ -119,7 +124,7 @@ } } } -@@ -343,7 +384,7 @@ +@@ -343,7 +386,7 @@ IBlockState iblockstate = this.func_180495_p(p_175655_1_); Block block = iblockstate.func_177230_c(); @@ -128,7 +133,7 @@ { return false; } -@@ -416,6 +457,9 @@ +@@ -416,6 +459,9 @@ public void func_175685_c(BlockPos p_175685_1_, Block p_175685_2_) { @@ -138,7 +143,7 @@ this.func_180496_d(p_175685_1_.func_177976_e(), p_175685_2_); this.func_180496_d(p_175685_1_.func_177974_f(), p_175685_2_); this.func_180496_d(p_175685_1_.func_177977_b(), p_175685_2_); -@@ -426,6 +470,11 @@ +@@ -426,6 +472,11 @@ public void func_175695_a(BlockPos p_175695_1_, Block p_175695_2_, EnumFacing p_175695_3_) { @@ -150,7 +155,7 @@ if (p_175695_3_ != EnumFacing.WEST) { this.func_180496_d(p_175695_1_.func_177976_e(), p_175695_2_); -@@ -521,7 +570,7 @@ +@@ -521,7 +572,7 @@ { IBlockState iblockstate = this.func_180495_p(blockpos); @@ -159,7 +164,7 @@ { return false; } -@@ -795,7 +844,7 @@ +@@ -795,7 +846,7 @@ public boolean func_72935_r() { @@ -168,7 +173,7 @@ } @Nullable -@@ -998,6 +1047,13 @@ +@@ -998,6 +1049,13 @@ public void func_184148_a(@Nullable EntityPlayer p_184148_1_, double p_184148_2_, double p_184148_4_, double p_184148_6_, SoundEvent p_184148_8_, SoundCategory p_184148_9_, float p_184148_10_, float p_184148_11_) { @@ -182,7 +187,7 @@ for (int i = 0; i < this.field_73021_x.size(); ++i) { ((IWorldEventListener)this.field_73021_x.get(i)).func_184375_a(p_184148_1_, p_184148_8_, p_184148_9_, p_184148_2_, p_184148_4_, p_184148_6_, p_184148_10_, p_184148_11_); -@@ -1043,6 +1099,9 @@ +@@ -1043,6 +1101,9 @@ public boolean func_72838_d(Entity p_72838_1_) { @@ -192,7 +197,7 @@ int i = MathHelper.func_76128_c(p_72838_1_.field_70165_t / 16.0D); int j = MathHelper.func_76128_c(p_72838_1_.field_70161_v / 16.0D); boolean flag = p_72838_1_.field_98038_p; -@@ -1065,6 +1124,8 @@ +@@ -1065,6 +1126,8 @@ this.func_72854_c(); } @@ -201,7 +206,7 @@ this.func_72964_e(i, j).func_76612_a(p_72838_1_); this.field_72996_f.add(p_72838_1_); this.func_72923_a(p_72838_1_); -@@ -1296,7 +1357,6 @@ +@@ -1296,7 +1359,6 @@ return list; } @@ -209,7 +214,7 @@ public void func_72848_b(IWorldEventListener p_72848_1_) { this.field_73021_x.remove(p_72848_1_); -@@ -1359,19 +1419,38 @@ +@@ -1359,19 +1421,38 @@ public int func_72967_a(float p_72967_1_) { @@ -250,7 +255,7 @@ float f = this.func_72826_c(p_72971_1_); float f1 = 1.0F - (MathHelper.func_76134_b(f * ((float)Math.PI * 2F)) * 2.0F + 0.2F); f1 = MathHelper.func_76131_a(f1, 0.0F, 1.0F); -@@ -1384,6 +1463,12 @@ +@@ -1384,6 +1465,12 @@ @SideOnly(Side.CLIENT) public Vec3d func_72833_a(Entity p_72833_1_, float p_72833_2_) { @@ -263,7 +268,7 @@ float f = this.func_72826_c(p_72833_2_); float f1 = MathHelper.func_76134_b(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F; f1 = MathHelper.func_76131_a(f1, 0.0F, 1.0F); -@@ -1391,9 +1476,7 @@ +@@ -1391,9 +1478,7 @@ int j = MathHelper.func_76128_c(p_72833_1_.field_70163_u); int k = MathHelper.func_76128_c(p_72833_1_.field_70161_v); BlockPos blockpos = new BlockPos(i, j, k); @@ -274,7 +279,7 @@ float f3 = (float)(l >> 16 & 255) / 255.0F; float f4 = (float)(l >> 8 & 255) / 255.0F; float f5 = (float)(l & 255) / 255.0F; -@@ -1453,6 +1536,11 @@ +@@ -1453,6 +1538,11 @@ public float func_130001_d() { @@ -286,7 +291,7 @@ return WorldProvider.field_111203_a[this.field_73011_w.func_76559_b(this.field_72986_A.func_76073_f())]; } -@@ -1465,6 +1553,12 @@ +@@ -1465,6 +1555,12 @@ @SideOnly(Side.CLIENT) public Vec3d func_72824_f(float p_72824_1_) { @@ -299,7 +304,7 @@ float f = this.func_72826_c(p_72824_1_); float f1 = MathHelper.func_76134_b(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F; f1 = MathHelper.func_76131_a(f1, 0.0F, 1.0F); -@@ -1520,9 +1614,9 @@ +@@ -1520,9 +1616,9 @@ for (blockpos = new BlockPos(p_175672_1_.func_177958_n(), chunk.func_76625_h() + 16, p_175672_1_.func_177952_p()); blockpos.func_177956_o() >= 0; blockpos = blockpos1) { blockpos1 = blockpos.func_177977_b(); @@ -311,7 +316,7 @@ { break; } -@@ -1534,6 +1628,12 @@ +@@ -1534,6 +1630,12 @@ @SideOnly(Side.CLIENT) public float func_72880_h(float p_72880_1_) { @@ -324,7 +329,7 @@ float f = this.func_72826_c(p_72880_1_); float f1 = 1.0F - (MathHelper.func_76134_b(f * ((float)Math.PI * 2F)) * 2.0F + 0.25F); f1 = MathHelper.func_76131_a(f1, 0.0F, 1.0F); -@@ -1585,6 +1685,12 @@ +@@ -1585,6 +1687,12 @@ entity.func_85029_a(crashreportcategory); } @@ -337,7 +342,7 @@ throw new ReportedException(crashreport); } -@@ -1646,6 +1752,12 @@ +@@ -1646,6 +1754,12 @@ CrashReport crashreport1 = CrashReport.func_85055_a(throwable1, "Ticking entity"); CrashReportCategory crashreportcategory1 = crashreport1.func_85058_a("Entity being ticked"); entity2.func_85029_a(crashreportcategory1); @@ -350,7 +355,7 @@ throw new ReportedException(crashreport1); } } -@@ -1682,7 +1794,7 @@ +@@ -1682,7 +1796,7 @@ { BlockPos blockpos = tileentity.func_174877_v(); @@ -359,7 +364,7 @@ { try { -@@ -1695,6 +1807,13 @@ +@@ -1695,6 +1809,13 @@ CrashReport crashreport2 = CrashReport.func_85055_a(throwable, "Ticking block entity"); CrashReportCategory crashreportcategory2 = crashreport2.func_85058_a("Block entity being ticked"); tileentity.func_145828_a(crashreportcategory2); @@ -373,7 +378,7 @@ throw new ReportedException(crashreport2); } } -@@ -1707,20 +1826,28 @@ +@@ -1707,20 +1828,28 @@ if (this.func_175667_e(tileentity.func_174877_v())) { @@ -405,7 +410,7 @@ this.field_72984_F.func_76318_c("pendingBlockEntities"); if (!this.field_147484_a.isEmpty()) -@@ -1759,8 +1886,12 @@ +@@ -1759,8 +1888,12 @@ public boolean func_175700_a(TileEntity p_175700_1_) { @@ -419,7 +424,7 @@ if (flag && p_175700_1_ instanceof ITickable) { this.field_175730_i.add(p_175700_1_); -@@ -1780,6 +1911,11 @@ +@@ -1780,6 +1913,11 @@ { if (this.field_147481_N) { @@ -431,7 +436,7 @@ this.field_147484_a.addAll(p_147448_1_); } else -@@ -1800,9 +1936,12 @@ +@@ -1800,9 +1938,12 @@ { int i = MathHelper.func_76128_c(p_72866_1_.field_70165_t); int j = MathHelper.func_76128_c(p_72866_1_.field_70161_v); @@ -446,7 +451,7 @@ { p_72866_1_.field_70142_S = p_72866_1_.field_70165_t; p_72866_1_.field_70137_T = p_72866_1_.field_70163_u; -@@ -2001,6 +2140,10 @@ +@@ -2001,6 +2142,10 @@ blockpos$pooledmutableblockpos.func_185344_t(); return true; } @@ -457,7 +462,7 @@ } } } -@@ -2040,6 +2183,16 @@ +@@ -2040,6 +2185,16 @@ IBlockState iblockstate = this.func_180495_p(blockpos$pooledmutableblockpos); Block block = iblockstate.func_177230_c(); @@ -474,7 +479,7 @@ if (iblockstate.func_185904_a() == p_72918_2_) { double d0 = (double)((float)(l1 + 1) - BlockLiquid.func_149801_b(((Integer)iblockstate.func_177229_b(BlockLiquid.field_176367_b)).intValue())); -@@ -2116,6 +2269,9 @@ +@@ -2116,6 +2271,9 @@ { IBlockState iblockstate = this.func_180495_p(blockpos$pooledmutableblockpos.func_181079_c(k1, l1, i2)); @@ -484,7 +489,7 @@ if (iblockstate.func_185904_a() == p_72830_2_) { int j2 = ((Integer)iblockstate.func_177229_b(BlockLiquid.field_176367_b)).intValue(); -@@ -2148,6 +2304,7 @@ +@@ -2148,6 +2306,7 @@ public Explosion func_72885_a(@Nullable Entity p_72885_1_, double p_72885_2_, double p_72885_4_, double p_72885_6_, float p_72885_8_, boolean p_72885_9_, boolean p_72885_10_) { Explosion explosion = new Explosion(this, p_72885_1_, p_72885_2_, p_72885_4_, p_72885_6_, p_72885_8_, p_72885_9_, p_72885_10_); @@ -492,7 +497,7 @@ explosion.func_77278_a(); explosion.func_77279_a(true); return explosion; -@@ -2270,6 +2427,7 @@ +@@ -2270,6 +2429,7 @@ public void func_175690_a(BlockPos p_175690_1_, @Nullable TileEntity p_175690_2_) { @@ -500,7 +505,7 @@ if (!this.func_189509_E(p_175690_1_)) { if (p_175690_2_ != null && !p_175690_2_.func_145837_r()) -@@ -2277,6 +2435,8 @@ +@@ -2277,6 +2437,8 @@ if (this.field_147481_N) { p_175690_2_.func_174878_a(p_175690_1_); @@ -509,7 +514,7 @@ Iterator iterator = this.field_147484_a.iterator(); while (iterator.hasNext()) -@@ -2295,8 +2455,10 @@ +@@ -2295,8 +2457,10 @@ else { this.func_175700_a(p_175690_2_); @@ -521,7 +526,7 @@ } } } -@@ -2309,6 +2471,8 @@ +@@ -2309,6 +2473,8 @@ { tileentity.func_145843_s(); this.field_147484_a.remove(tileentity); @@ -530,7 +535,7 @@ } else { -@@ -2321,6 +2485,7 @@ +@@ -2321,6 +2487,7 @@ this.func_175726_f(p_175713_1_).func_177425_e(p_175713_1_); } @@ -538,7 +543,7 @@ } public void func_147457_a(TileEntity p_147457_1_) -@@ -2347,7 +2512,7 @@ +@@ -2347,7 +2514,7 @@ if (chunk != null && !chunk.func_76621_g()) { IBlockState iblockstate = this.func_180495_p(p_175677_1_); @@ -547,7 +552,7 @@ } else { -@@ -2370,6 +2535,7 @@ +@@ -2370,6 +2537,7 @@ { this.field_72985_G = p_72891_1_; this.field_72992_H = p_72891_2_; @@ -555,7 +560,7 @@ } public void func_72835_b() -@@ -2379,6 +2545,11 @@ +@@ -2379,6 +2547,11 @@ protected void func_72947_a() { @@ -567,7 +572,7 @@ if (this.field_72986_A.func_76059_o()) { this.field_73004_o = 1.0F; -@@ -2392,6 +2563,11 @@ +@@ -2392,6 +2565,11 @@ protected void func_72979_l() { @@ -579,7 +584,7 @@ if (!this.field_73011_w.func_177495_o()) { if (!this.field_72995_K) -@@ -2511,6 +2687,11 @@ +@@ -2511,6 +2689,11 @@ public boolean func_175670_e(BlockPos p_175670_1_, boolean p_175670_2_) { @@ -591,7 +596,7 @@ Biome biome = this.func_180494_b(p_175670_1_); float f = biome.func_180626_a(p_175670_1_); -@@ -2552,6 +2733,11 @@ +@@ -2552,6 +2735,11 @@ public boolean func_175708_f(BlockPos p_175708_1_, boolean p_175708_2_) { @@ -603,7 +608,7 @@ Biome biome = this.func_180494_b(p_175708_1_); float f = biome.func_180626_a(p_175708_1_); -@@ -2569,7 +2755,7 @@ +@@ -2569,7 +2757,7 @@ { IBlockState iblockstate = this.func_180495_p(p_175708_1_); @@ -612,7 +617,7 @@ { return true; } -@@ -2601,10 +2787,11 @@ +@@ -2601,10 +2789,11 @@ else { IBlockState iblockstate = this.func_180495_p(p_175638_1_); @@ -627,7 +632,7 @@ { j = 1; } -@@ -2703,7 +2890,7 @@ +@@ -2703,7 +2892,7 @@ int j4 = j2 + enumfacing.func_96559_d(); int k4 = k2 + enumfacing.func_82599_e(); blockpos$pooledmutableblockpos.func_181079_c(i4, j4, k4); @@ -636,7 +641,7 @@ i3 = this.func_175642_b(p_180500_1_, blockpos$pooledmutableblockpos); if (i3 == l2 - l4 && j < this.field_72994_J.length) -@@ -2811,10 +2998,10 @@ +@@ -2811,10 +3000,10 @@ public List func_175674_a(@Nullable Entity p_175674_1_, AxisAlignedBB p_175674_2_, @Nullable Predicate p_175674_3_) { List list = Lists.newArrayList(); @@ -651,7 +656,7 @@ for (int i1 = i; i1 <= j; ++i1) { -@@ -2867,10 +3054,10 @@ +@@ -2867,10 +3056,10 @@ public List func_175647_a(Class p_175647_1_, AxisAlignedBB p_175647_2_, @Nullable Predicate p_175647_3_) { @@ -666,7 +671,7 @@ List list = Lists.newArrayList(); for (int i1 = i; i1 < j; ++i1) -@@ -2950,11 +3137,13 @@ +@@ -2950,11 +3139,13 @@ public void func_175650_b(Collection p_175650_1_) { @@ -683,7 +688,7 @@ } } -@@ -2967,7 +3156,7 @@ +@@ -2967,7 +3158,7 @@ { IBlockState iblockstate = this.func_180495_p(p_175716_2_); AxisAlignedBB axisalignedbb = p_175716_3_ ? null : p_175716_1_.func_176223_P().func_185890_d(this, p_175716_2_); @@ -692,7 +697,7 @@ } public int func_181545_F() -@@ -3050,7 +3239,7 @@ +@@ -3050,7 +3241,7 @@ public int func_175651_c(BlockPos p_175651_1_, EnumFacing p_175651_2_) { IBlockState iblockstate = this.func_180495_p(p_175651_1_); @@ -701,7 +706,7 @@ } public boolean func_175640_z(BlockPos p_175640_1_) -@@ -3247,7 +3436,7 @@ +@@ -3247,7 +3438,7 @@ public long func_72905_C() { @@ -710,7 +715,7 @@ } public long func_82737_E() -@@ -3257,17 +3446,17 @@ +@@ -3257,17 +3448,17 @@ public long func_72820_D() { @@ -731,7 +736,7 @@ if (!this.func_175723_af().func_177746_a(blockpos)) { -@@ -3279,7 +3468,7 @@ +@@ -3279,7 +3470,7 @@ public void func_175652_B(BlockPos p_175652_1_) { @@ -740,7 +745,7 @@ } @SideOnly(Side.CLIENT) -@@ -3299,12 +3488,18 @@ +@@ -3299,12 +3490,18 @@ if (!this.field_72996_f.contains(p_72897_1_)) { @@ -759,7 +764,7 @@ return true; } -@@ -3398,8 +3593,7 @@ +@@ -3398,8 +3595,7 @@ public boolean func_180502_D(BlockPos p_180502_1_) { @@ -769,7 +774,7 @@ } @Nullable -@@ -3460,12 +3654,12 @@ +@@ -3460,12 +3656,12 @@ public int func_72800_K() { @@ -784,7 +789,7 @@ } public Random func_72843_D(int p_72843_1_, int p_72843_2_, int p_72843_3_) -@@ -3509,7 +3703,7 @@ +@@ -3509,7 +3705,7 @@ @SideOnly(Side.CLIENT) public double func_72919_O() { @@ -793,7 +798,7 @@ } public void func_175715_c(int p_175715_1_, BlockPos p_175715_2_, int p_175715_3_) -@@ -3543,7 +3737,7 @@ +@@ -3543,7 +3739,7 @@ public void func_175666_e(BlockPos p_175666_1_, Block p_175666_2_) { @@ -802,7 +807,7 @@ { BlockPos blockpos = p_175666_1_.func_177972_a(enumfacing); -@@ -3551,18 +3745,14 @@ +@@ -3551,18 +3747,14 @@ { IBlockState iblockstate = this.func_180495_p(blockpos); @@ -825,7 +830,7 @@ } } } -@@ -3628,6 +3818,87 @@ +@@ -3628,6 +3820,112 @@ return i >= -128 && i <= 128 && j >= -128 && j <= 128; } @@ -904,6 +909,31 @@ + return count; + } + ++ protected void initCapabilities() ++ { ++ net.minecraftforge.common.capabilities.ICapabilityProvider parent = field_73011_w.initCapabilities(); ++ capabilities = net.minecraftforge.event.ForgeEventFactory.gatherCapabilities(this, parent); ++ net.minecraftforge.common.util.WorldCapabilityData data = (net.minecraftforge.common.util.WorldCapabilityData)perWorldStorage.func_75742_a(net.minecraftforge.common.util.WorldCapabilityData.class, net.minecraftforge.common.util.WorldCapabilityData.ID); ++ if (data == null) ++ { ++ capabilityData = new net.minecraftforge.common.util.WorldCapabilityData(capabilities); ++ perWorldStorage.func_75745_a(capabilityData.field_76190_i, capabilityData); ++ } ++ else ++ { ++ capabilityData = data; ++ capabilityData.setCapabilities(field_73011_w, capabilities); ++ } ++ } ++ public boolean hasCapability(net.minecraftforge.common.capabilities.Capability capability, EnumFacing facing) ++ { ++ return capabilities == null ? false : capabilities.hasCapability(capability, facing); ++ } ++ public T getCapability(net.minecraftforge.common.capabilities.Capability capability, EnumFacing facing) ++ { ++ return capabilities == null ? null : capabilities.getCapability(capability, facing); ++ } ++ + protected MapStorage perWorldStorage; //Moved to a getter to simulate final without being final so we can load in subclasses. + public MapStorage getPerWorldStorage() + { diff --git a/patches/minecraft/net/minecraft/world/WorldProvider.java.patch b/patches/minecraft/net/minecraft/world/WorldProvider.java.patch index 1930a42589..77b782a58d 100644 --- a/patches/minecraft/net/minecraft/world/WorldProvider.java.patch +++ b/patches/minecraft/net/minecraft/world/WorldProvider.java.patch @@ -54,7 +54,7 @@ } @SideOnly(Side.CLIENT) -@@ -214,6 +200,327 @@ +@@ -214,6 +200,339 @@ return new WorldBorder(); } @@ -220,6 +220,18 @@ + return 0; + } + ++ /** ++ * Called from {@link World#initCapabilities()}, to gather capabilities for this world. ++ * It's safe to access world here since this is called after world is registered. ++ * ++ * On server, called directly after mapStorage and world data such as Scoreboard and VillageCollection are initialized. ++ * On client, called when world is constructed, just before world load event is called. ++ * Note that this method is always called before the world load event. ++ * @return initial holder for capabilities on the world ++ */ ++ public net.minecraftforge.common.capabilities.ICapabilityProvider initCapabilities() { ++ return null; ++ } + /*======================================= Start Moved From World =========================================*/ + + public Biome getBiomeForCoords(BlockPos pos) diff --git a/patches/minecraft/net/minecraft/world/WorldServer.java.patch b/patches/minecraft/net/minecraft/world/WorldServer.java.patch index 39103b4e3c..cc3e32304c 100644 --- a/patches/minecraft/net/minecraft/world/WorldServer.java.patch +++ b/patches/minecraft/net/minecraft/world/WorldServer.java.patch @@ -43,7 +43,15 @@ } else { -@@ -215,6 +224,10 @@ +@@ -156,6 +165,7 @@ + this.func_175723_af().func_177750_a(this.field_72986_A.func_176137_E()); + } + ++ this.initCapabilities(); + return this; + } + +@@ -215,6 +225,10 @@ this.field_175740_d.func_75528_a(); this.field_72984_F.func_76318_c("portalForcer"); this.field_85177_Q.func_85189_a(this.func_82737_E()); @@ -54,7 +62,7 @@ this.field_72984_F.func_76319_b(); this.func_147488_Z(); } -@@ -223,12 +236,14 @@ +@@ -223,12 +237,14 @@ public Biome.SpawnListEntry func_175734_a(EnumCreatureType p_175734_1_, BlockPos p_175734_2_) { List list = this.func_72863_F().func_177458_a(p_175734_1_, p_175734_2_); @@ -69,7 +77,7 @@ return list != null && !list.isEmpty() ? list.contains(p_175732_2_) : false; } -@@ -274,10 +289,7 @@ +@@ -274,10 +290,7 @@ private void func_73051_P() { @@ -81,7 +89,7 @@ } public boolean func_73056_e() -@@ -370,7 +382,7 @@ +@@ -370,7 +383,7 @@ boolean flag1 = this.func_72911_I(); this.field_72984_F.func_76320_a("pollingChunks"); @@ -90,7 +98,7 @@ { this.field_72984_F.func_76320_a("getChunk"); Chunk chunk = (Chunk)iterator.next(); -@@ -382,7 +394,7 @@ +@@ -382,7 +395,7 @@ chunk.func_150804_b(false); this.field_72984_F.func_76318_c("thunder"); @@ -99,7 +107,7 @@ { this.field_73005_l = this.field_73005_l * 3 + 1013904223; int l = this.field_73005_l >> 2; -@@ -411,7 +423,7 @@ +@@ -411,7 +424,7 @@ this.field_72984_F.func_76318_c("iceandsnow"); @@ -108,7 +116,7 @@ { this.field_73005_l = this.field_73005_l * 3 + 1013904223; int j2 = this.field_73005_l >> 2; -@@ -527,7 +539,10 @@ +@@ -527,7 +540,10 @@ { if (p_175654_2_.func_149698_L()) { @@ -120,7 +128,7 @@ { IBlockState iblockstate = this.func_180495_p(p_175654_1_); -@@ -587,7 +602,7 @@ +@@ -587,7 +603,7 @@ public void func_72939_s() { @@ -129,7 +137,7 @@ { if (this.field_80004_Q++ >= 300) { -@@ -711,6 +726,9 @@ +@@ -711,6 +727,9 @@ { NextTickListEntry nextticklistentry1 = (NextTickListEntry)iterator.next(); iterator.remove(); @@ -139,7 +147,7 @@ int k = 0; if (this.func_175707_a(nextticklistentry1.field_180282_a.func_177982_a(0, 0, 0), nextticklistentry1.field_180282_a.func_177982_a(0, 0, 0))) -@@ -837,6 +855,10 @@ +@@ -837,6 +856,10 @@ public boolean func_175660_a(EntityPlayer p_175660_1_, BlockPos p_175660_2_) { @@ -150,7 +158,7 @@ return !this.field_73061_a.func_175579_a(this, p_175660_2_, p_175660_1_) && this.func_175723_af().func_177746_a(p_175660_2_); } -@@ -902,6 +924,7 @@ +@@ -902,6 +925,7 @@ } else { @@ -158,7 +166,7 @@ this.field_72987_B = true; BiomeProvider biomeprovider = this.field_73011_w.func_177499_m(); List list = biomeprovider.func_76932_a(); -@@ -986,6 +1009,7 @@ +@@ -986,6 +1010,7 @@ } chunkproviderserver.func_186027_a(p_73044_1_); @@ -166,7 +174,7 @@ for (Chunk chunk : Lists.newArrayList(chunkproviderserver.func_189548_a())) { -@@ -1030,6 +1054,7 @@ +@@ -1030,6 +1055,7 @@ this.field_72986_A.func_176135_e(this.func_175723_af().func_177732_i()); this.field_73019_z.func_75755_a(this.field_72986_A, this.field_73061_a.func_184103_al().func_72378_q()); this.field_72988_C.func_75744_a(); @@ -174,7 +182,7 @@ } public boolean func_72838_d(Entity p_72838_1_) -@@ -1041,7 +1066,7 @@ +@@ -1041,7 +1067,7 @@ { for (Entity entity : Lists.newArrayList(p_175650_1_)) { @@ -183,7 +191,7 @@ { this.field_72996_f.add(entity); this.func_72923_a(entity); -@@ -1122,7 +1147,7 @@ +@@ -1122,7 +1148,7 @@ { if (super.func_72942_c(p_72942_1_)) { @@ -192,7 +200,7 @@ return true; } else -@@ -1144,6 +1169,7 @@ +@@ -1144,6 +1170,7 @@ public Explosion func_72885_a(@Nullable Entity p_72885_1_, double p_72885_2_, double p_72885_4_, double p_72885_6_, float p_72885_8_, boolean p_72885_9_, boolean p_72885_10_) { Explosion explosion = new Explosion(this, p_72885_1_, p_72885_2_, p_72885_4_, p_72885_6_, p_72885_8_, p_72885_9_, p_72885_10_); @@ -200,7 +208,7 @@ explosion.func_77278_a(); explosion.func_77279_a(false); -@@ -1189,7 +1215,7 @@ +@@ -1189,7 +1216,7 @@ { if (this.func_147485_a(blockeventdata)) { @@ -209,7 +217,7 @@ } } -@@ -1215,27 +1241,31 @@ +@@ -1215,27 +1242,31 @@ if (this.field_73003_n != this.field_73004_o) { @@ -247,7 +255,7 @@ } } -@@ -1314,6 +1344,11 @@ +@@ -1314,6 +1345,11 @@ return this.field_73061_a.func_152345_ab(); } diff --git a/patches/minecraft/net/minecraft/world/WorldServerMulti.java.patch b/patches/minecraft/net/minecraft/world/WorldServerMulti.java.patch index a5fdfe84d2..121f7da8fa 100644 --- a/patches/minecraft/net/minecraft/world/WorldServerMulti.java.patch +++ b/patches/minecraft/net/minecraft/world/WorldServerMulti.java.patch @@ -45,7 +45,11 @@ } else { -@@ -75,6 +78,14 @@ +@@ -72,9 +75,18 @@ + this.field_72982_D.func_82566_a(this); + } + ++ this.initCapabilities(); return this; } diff --git a/src/main/java/net/minecraftforge/common/util/WorldCapabilityData.java b/src/main/java/net/minecraftforge/common/util/WorldCapabilityData.java new file mode 100644 index 0000000000..8ffff90a2d --- /dev/null +++ b/src/main/java/net/minecraftforge/common/util/WorldCapabilityData.java @@ -0,0 +1,57 @@ +package net.minecraftforge.common.util; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.WorldProvider; +import net.minecraft.world.WorldSavedData; + +public class WorldCapabilityData extends WorldSavedData +{ + public static final String ID = "capabilities"; + + private INBTSerializable serializable; + private NBTTagCompound capNBT = null; + + public WorldCapabilityData(String name) + { + super(name); + } + + public WorldCapabilityData(INBTSerializable serializable) + { + super(ID); + this.serializable = serializable; + } + + @Override + public void readFromNBT(NBTTagCompound nbt) + { + this.capNBT = nbt; + if(serializable != null) + { + serializable.deserializeNBT(this.capNBT); + this.capNBT = null; + } + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) + { + return nbt = serializable.serializeNBT(); + } + + @Override + public boolean isDirty() + { + return true; + } + + public void setCapabilities(WorldProvider provider, INBTSerializable capabilities) + { + this.serializable = capabilities; + if(this.capNBT != null) + { + serializable.deserializeNBT(this.capNBT); + this.capNBT = null; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/event/AttachCapabilitiesEvent.java b/src/main/java/net/minecraftforge/event/AttachCapabilitiesEvent.java index 4166a1e09a..fd8bfa05de 100644 --- a/src/main/java/net/minecraftforge/event/AttachCapabilitiesEvent.java +++ b/src/main/java/net/minecraftforge/event/AttachCapabilitiesEvent.java @@ -133,4 +133,21 @@ public class AttachCapabilitiesEvent extends Event return this.stack; } } + + /** + * A version of the parent event which is only fired for Worlds. + */ + public static class World extends AttachCapabilitiesEvent + { + private final net.minecraft.world.World world; + public World(net.minecraft.world.World world) + { + super(world); + this.world = world; + } + public net.minecraft.world.World getWorld() + { + return this.world; + } + } } diff --git a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index aa88cccb02..7593041f75 100644 --- a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -525,6 +525,10 @@ public class ForgeEventFactory return gatherCapabilities(new AttachCapabilitiesEvent.Item(item, stack), parent); } + public static CapabilityDispatcher gatherCapabilities(World world, ICapabilityProvider parent) { + return gatherCapabilities(new AttachCapabilitiesEvent.World(world), parent); + } + private static CapabilityDispatcher gatherCapabilities(AttachCapabilitiesEvent event, ICapabilityProvider parent) { MinecraftForge.EVENT_BUS.post(event); diff --git a/src/test/java/net/minecraftforge/test/WorldCapabilityRainTimerTest.java b/src/test/java/net/minecraftforge/test/WorldCapabilityRainTimerTest.java new file mode 100644 index 0000000000..bc1a3489c9 --- /dev/null +++ b/src/test/java/net/minecraftforge/test/WorldCapabilityRainTimerTest.java @@ -0,0 +1,167 @@ +package net.minecraftforge.test; + +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.Maps; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagIntArray; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.storage.WorldInfo; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.Capability.IStorage; +import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; +import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +/** Simple mod to test world capability, by adding timer logic and check for raining time. */ +@Mod(modid=WorldCapabilityRainTimerTest.MODID, name="World Periodic Rain Check Test", version="0.0.0") +public class WorldCapabilityRainTimerTest { + public static final String MODID = "worldperiodicrainchecktest"; + + @CapabilityInject(IRainTimer.class) + public static final Capability TIMER_CAP = null; + + @EventHandler + public void init(FMLInitializationEvent event) + { + CapabilityManager.INSTANCE.register(IRainTimer.class, new TimerStorage(), DefaultTimer.class); + MinecraftForge.EVENT_BUS.register(new NormalEventHandler()); + } + + public static class NormalEventHandler + { + @SubscribeEvent + public void attatchTimer(AttachCapabilitiesEvent.World event) + { + event.addCapability(new ResourceLocation(MODID, "rainTimer"), new RainTimerProvider()); + } + + @SubscribeEvent + public void onTick(TickEvent.WorldTickEvent event) + { + if(event.world.isRemote) + return; + + IRainTimer timer = event.world.getCapability(TIMER_CAP, null); + + if(event.phase == TickEvent.Phase.END) + timer.onTick(); + + if(event.phase == TickEvent.Phase.START) + { + if(!event.world.provider.getHasNoSky() && event.world.isRaining()) + { + if(timer.getDuration() == 0) + timer.refreshTimer(1000, 0); + else if(timer.isTimerReachedDuration()) + event.world.provider.resetRainAndThunder(); + } else + timer.refreshTimer(0, 0); + } + } + } + + public interface IRainTimer + { + public int getCurrentTime(); + public int getDuration(); + + public void refreshTimer(int duration, int initial); + public void resetTimer(); + public boolean isTimerReachedDuration(); + + public void onTick(); + } + + public static class TimerStorage implements IStorage + { + @Override + public NBTBase writeNBT(Capability capability, IRainTimer instance, EnumFacing side) { + NBTTagCompound compound = new NBTTagCompound(); + compound.setInteger("current", instance.getCurrentTime()); + compound.setInteger("duration", instance.getDuration()); + return compound; + } + + @Override + public void readNBT(Capability capability, IRainTimer instance, EnumFacing side, NBTBase nbt) { + NBTTagCompound data = (NBTTagCompound) nbt; + instance.refreshTimer(data.getInteger("duration"), data.getInteger("current")); + } + } + + public static class DefaultTimer implements IRainTimer + { + private int duration, current; + + @Override + public int getCurrentTime() { return this.current; } + @Override + public int getDuration() { return this.duration; } + + @Override + public void refreshTimer(int duration, int initial) + { + this.duration = duration; + this.current = initial; + } + + @Override + public void resetTimer() + { + this.current = 0; + } + @Override + public boolean isTimerReachedDuration() + { + return this.current >= this.duration; + } + + @Override + public void onTick() + { + if(this.current < this.duration) + this.current++; + } + } + + public static class RainTimerProvider implements ICapabilitySerializable + { + private IRainTimer timer = TIMER_CAP.getDefaultInstance(); + + @Override + public boolean hasCapability(Capability capability, EnumFacing facing) + { + return capability == TIMER_CAP; + } + + @Override + public T getCapability(Capability capability, EnumFacing facing) + { + return capability == TIMER_CAP? TIMER_CAP.cast(this.timer) : null; + } + + @Override + public NBTTagCompound serializeNBT() + { + return (NBTTagCompound) TIMER_CAP.writeNBT(this.timer, null); + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) + { + TIMER_CAP.readNBT(this.timer, null, nbt); + } + } +} \ No newline at end of file