diff --git a/build.gradle b/build.gradle index acbf07f..7055ddd 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ def folder = "javascript" def name = "classes.js" teavm.js { - obfuscated = true + obfuscated = false sourceMap = true targetFileName = "../" + name optimization = OptimizationLevel.BALANCED // Change to "AGGRESSIVE" for release @@ -56,17 +56,17 @@ teavm.js { debugInformation = false } -tasks.named("generateJavaScript") { - doLast { +// tasks.named("generateJavaScript") { +// doLast { - // NOTE: This step may break at any time, and is not required for 99% of browsers +// // NOTE: This step may break at any time, and is not required for 99% of browsers - def phile = file(folder + "/" + name) - def dest = phile.getText("UTF-8") - def i = dest.substring(0, dest.indexOf("=\$rt_globals.Symbol('jsoClass');")).lastIndexOf("let ") - dest = dest.substring(0, i) + "var" + dest.substring(i + 3) - def j = dest.indexOf("function(\$rt_globals,\$rt_exports){") - dest = dest.substring(0, j + 34) + "\n" + file(folder + "/ES6ShimScript.txt").getText("UTF-8") + "\n" + dest.substring(j + 34) - phile.write(dest, "UTF-8") - } -} \ No newline at end of file +// def phile = file(folder + "/" + name) +// def dest = phile.getText("UTF-8") +// def i = dest.substring(0, dest.indexOf("=\$rt_globals.Symbol('jsoClass');")).lastIndexOf("let ") +// dest = dest.substring(0, i) + "var" + dest.substring(i + 3) +// def j = dest.indexOf("function(\$rt_globals,\$rt_exports){") +// dest = dest.substring(0, j + 34) + "\n" + file(folder + "/ES6ShimScript.txt").getText("UTF-8") + "\n" + dest.substring(j + 34) +// phile.write(dest, "UTF-8") +// } +// } \ No newline at end of file diff --git a/resources/resources/assets/minecraft/server/test.txt b/resources/resources/assets/minecraft/server/test.txt new file mode 100644 index 0000000..8def50d --- /dev/null +++ b/resources/resources/assets/minecraft/server/test.txt @@ -0,0 +1 @@ +hello :3 \ No newline at end of file diff --git a/resources/resources/assets/minecraft/sounds.json b/resources/resources/assets/minecraft/sounds.json index 9a26e83..4aab198 100644 --- a/resources/resources/assets/minecraft/sounds.json +++ b/resources/resources/assets/minecraft/sounds.json @@ -1678,6 +1678,23 @@ "random/glass3" ] }, + "block.chorus_flower.grow": { + "category": "block", + "sounds": [ + "block/chorus_flower/grow1", + "block/chorus_flower/grow2", + "block/chorus_flower/grow3", + "block/chorus_flower/grow4" + ] + }, + "block.chorus_flower.death": { + "category": "block", + "sounds": [ + "block/chorus_flower/death1", + "block/chorus_flower/death2", + "block/chorus_flower/death3" + ] + }, "game.potion.smash": { "category": "neutral", "sounds": [ diff --git a/resources/resources/assets/minecraft/sounds/block/chorus_flower/death1.ogg b/resources/resources/assets/minecraft/sounds/block/chorus_flower/death1.ogg new file mode 100644 index 0000000..f1d1c25 Binary files /dev/null and b/resources/resources/assets/minecraft/sounds/block/chorus_flower/death1.ogg differ diff --git a/resources/resources/assets/minecraft/sounds/block/chorus_flower/death2.ogg b/resources/resources/assets/minecraft/sounds/block/chorus_flower/death2.ogg new file mode 100644 index 0000000..9068946 Binary files /dev/null and b/resources/resources/assets/minecraft/sounds/block/chorus_flower/death2.ogg differ diff --git a/resources/resources/assets/minecraft/sounds/block/chorus_flower/death3.ogg b/resources/resources/assets/minecraft/sounds/block/chorus_flower/death3.ogg new file mode 100644 index 0000000..51abd64 Binary files /dev/null and b/resources/resources/assets/minecraft/sounds/block/chorus_flower/death3.ogg differ diff --git a/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow1.ogg b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow1.ogg new file mode 100644 index 0000000..1717e60 Binary files /dev/null and b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow1.ogg differ diff --git a/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow2.ogg b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow2.ogg new file mode 100644 index 0000000..43dd88e Binary files /dev/null and b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow2.ogg differ diff --git a/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow3.ogg b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow3.ogg new file mode 100644 index 0000000..5d93113 Binary files /dev/null and b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow3.ogg differ diff --git a/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow4.ogg b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow4.ogg new file mode 100644 index 0000000..3c1c343 Binary files /dev/null and b/resources/resources/assets/minecraft/sounds/block/chorus_flower/grow4.ogg differ diff --git a/src/game/java/net/minecraft/block/BlockChorusFlower.java b/src/game/java/net/minecraft/block/BlockChorusFlower.java index 561cc3f..4d86597 100644 --- a/src/game/java/net/minecraft/block/BlockChorusFlower.java +++ b/src/game/java/net/minecraft/block/BlockChorusFlower.java @@ -126,13 +126,12 @@ public class BlockChorusFlower extends Block { private void placeGrownFlower(World p_185602_1_, BlockPos p_185602_2_, int p_185602_3_) { p_185602_1_.setBlockState(p_185602_2_, this.getDefaultState().withProperty(AGE, Integer.valueOf(p_185602_3_)), 2); - // TODO: implement soundf - // p_185602_1_.playAuxSFX(1033, p_185602_2_, 0); + p_185602_1_.playAuxSFX(1033, p_185602_2_, 0); } private void placeDeadFlower(World p_185605_1_, BlockPos p_185605_2_) { p_185605_1_.setBlockState(p_185605_2_, this.getDefaultState().withProperty(AGE, Integer.valueOf(5)), 2); - // p_185605_1_.playAuxSFX(1034, p_185605_2_, 0); + p_185605_1_.playAuxSFX(1034, p_185605_2_, 0); } private static boolean areAllNeighborsEmpty(World p_185604_0_, BlockPos p_185604_1_, EnumFacing p_185604_2_) { @@ -270,7 +269,7 @@ public class BlockChorusFlower extends Block { if (!flag) { worldIn.setBlockState(p_185601_1_.up(i), - EaglerItems.getEaglerBlock("chorus_plant").getDefaultState().withProperty(AGE, Integer.valueOf(5)), + EaglerItems.getEaglerBlock("chorus_flower").getDefaultState().withProperty(AGE, Integer.valueOf(5)), 2); } } diff --git a/src/game/java/net/minecraft/client/renderer/RenderGlobal.java b/src/game/java/net/minecraft/client/renderer/RenderGlobal.java index 1ebd04d..1a7c4fd 100644 --- a/src/game/java/net/minecraft/client/renderer/RenderGlobal.java +++ b/src/game/java/net/minecraft/client/renderer/RenderGlobal.java @@ -49,6 +49,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.audio.SoundCategory; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.chunk.CompiledChunk; @@ -2390,6 +2391,12 @@ public class RenderGlobal implements IWorldAccess, IResourceManagerReloadListene this.theWorld.playSoundAtPos(blockpos, "random.anvil_land", 0.3F, this.theWorld.rand.nextFloat() * 0.1F + 0.9F, false); break; + case 1033: + this.theWorld.playSoundAtPos(blockpos, "block.chorus_flower.grow", 1.0F, 1.0F, false); + break; + case 1034: + this.theWorld.playSoundAtPos(blockpos, "block.chorus_flower.death", 1.0F, 1.0F, false); + break; case 2000: int j1 = j % 3 - 1; int k = j / 3 % 3 - 1; diff --git a/src/game/java/net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.java b/src/game/java/net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.java index d7b4d14..d39d87c 100644 --- a/src/game/java/net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.java +++ b/src/game/java/net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.java @@ -64,16 +64,18 @@ public class TileEntityItemStackRenderer { if (itemStackIn.getItem() == Items.banner) { this.banner.setItemValues(itemStackIn); TileEntityRendererDispatcher.instance.renderTileEntityAt(this.banner, 0.0D, 0.0D, 0.0D, 0.0F); - } else if (itemStackIn.getItem() == EaglerItems.getEaglerItem("shield")) { - { - Minecraft.getMinecraft().getTextureManager().bindTexture(SHIELD_BASE_TEXTURE); + } + // else if (itemStackIn.getItem() == EaglerItems.getEaglerItem("shield")) { + // { + // Minecraft.getMinecraft().getTextureManager().bindTexture(SHIELD_BASE_TEXTURE); - GlStateManager.pushMatrix(); - GlStateManager.scale(1.0F, -1.0F, -1.0F); - this.modelShield.render(); - GlStateManager.popMatrix(); - } - } else if (itemStackIn.getItem() == Items.skull) { + // GlStateManager.pushMatrix(); + // GlStateManager.scale(1.0F, -1.0F, -1.0F); + // this.modelShield.render(); + // GlStateManager.popMatrix(); + // } + // } + else if (itemStackIn.getItem() == Items.skull) { GameProfile gameprofile = null; if (itemStackIn.hasTagCompound()) { NBTTagCompound nbttagcompound = itemStackIn.getTagCompound(); diff --git a/src/game/java/net/minecraft/entity/Entity.java b/src/game/java/net/minecraft/entity/Entity.java index 5329e4c..b8d93cb 100644 --- a/src/game/java/net/minecraft/entity/Entity.java +++ b/src/game/java/net/minecraft/entity/Entity.java @@ -2323,18 +2323,18 @@ public abstract class Entity implements ICommandSender { return Entity.this.getName(); } }); - category.addCrashSection("Entity\'s Exact location", String.format("%.2f, %.2f, %.2f", - new Object[] { Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ) })); - category.addCrashSection("Entity\'s Block location", - CrashReportCategory.getCoordinateInfo((double) MathHelper.floor_double(this.posX), - (double) MathHelper.floor_double(this.posY), (double) MathHelper.floor_double(this.posZ))); - category.addCrashSection("Entity\'s Momentum", String.format("%.2f, %.2f, %.2f", new Object[] { - Double.valueOf(this.motionX), Double.valueOf(this.motionY), Double.valueOf(this.motionZ) })); - category.addCrashSectionCallable("Entity\'s Rider", new Callable() { - public String call() throws Exception { - return Entity.this.riddenByEntity.toString(); - } - }); + // category.addCrashSection("Entity\'s Exact location", String.format("%.2f, %.2f, %.2f", + // new Object[] { Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ) })); + // category.addCrashSection("Entity\'s Block location", + // CrashReportCategory.getCoordinateInfo((double) MathHelper.floor_double(this.posX), + // (double) MathHelper.floor_double(this.posY), (double) MathHelper.floor_double(this.posZ))); + // category.addCrashSection("Entity\'s Momentum", String.format("%.2f, %.2f, %.2f", new Object[] { + // Double.valueOf(this.motionX), Double.valueOf(this.motionY), Double.valueOf(this.motionZ) })); + // category.addCrashSectionCallable("Entity\'s Rider", new Callable() { + // public String call() throws Exception { + // return Entity.this.riddenByEntity.toString(); + // } + // }); category.addCrashSectionCallable("Entity\'s Vehicle", new Callable() { public String call() throws Exception { return Entity.this.ridingEntity.toString(); diff --git a/src/game/java/net/minecraft/world/gen/ChunkProviderEnd.java b/src/game/java/net/minecraft/world/gen/ChunkProviderEnd.java index 757d187..d2cb420 100644 --- a/src/game/java/net/minecraft/world/gen/ChunkProviderEnd.java +++ b/src/game/java/net/minecraft/world/gen/ChunkProviderEnd.java @@ -2,6 +2,7 @@ package net.minecraft.world.gen; import java.util.List; import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; +import net.minecraft.block.BlockChorusFlower; import net.minecraft.block.BlockFalling; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -15,6 +16,7 @@ import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkPrimer; import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.feature.WorldGenEndIsland; /** * + @@ -46,73 +48,85 @@ import net.minecraft.world.chunk.IChunkProvider; * */ public class ChunkProviderEnd implements IChunkProvider { - private EaglercraftRandom endRNG; - private NoiseGeneratorOctaves noiseGen1; - private NoiseGeneratorOctaves noiseGen2; - private NoiseGeneratorOctaves noiseGen3; - public NoiseGeneratorOctaves noiseGen4; + private EaglercraftRandom rand; + protected static final IBlockState END_STONE = Blocks.end_stone.getDefaultState(); + protected static final IBlockState AIR = Blocks.air.getDefaultState(); + private final NoiseGeneratorOctaves lperlinNoise1; + private final NoiseGeneratorOctaves lperlinNoise2; + private final NoiseGeneratorOctaves perlinNoise1; + public NoiseGeneratorOctaves noiseGen5; - private World endWorld; - private double[] densities; + + public NoiseGeneratorOctaves noiseGen6; + + private final World worldObj; + + private final boolean mapFeaturesEnabled; + // private final MapGenEndCity endCityGen = new MapGenEndCity(this); + private final NoiseGeneratorSimplex islandNoise; + private double[] buffer; + private BiomeGenBase[] biomesForGeneration; - double[] noiseData1; - double[] noiseData2; - double[] noiseData3; - double[] noiseData4; - double[] noiseData5; + double[] pnr; + double[] ar; + double[] br; + private final WorldGenEndIsland endIslands = new WorldGenEndIsland(); public ChunkProviderEnd(World worldIn, long parLong1) { - this.endWorld = worldIn; - this.endRNG = new EaglercraftRandom(parLong1, !worldIn.getWorldInfo().isOldEaglercraftRandom()); - this.noiseGen1 = new NoiseGeneratorOctaves(this.endRNG, 16); - this.noiseGen2 = new NoiseGeneratorOctaves(this.endRNG, 16); - this.noiseGen3 = new NoiseGeneratorOctaves(this.endRNG, 8); - this.noiseGen4 = new NoiseGeneratorOctaves(this.endRNG, 10); - this.noiseGen5 = new NoiseGeneratorOctaves(this.endRNG, 16); + this.worldObj = worldIn; + this.mapFeaturesEnabled = true; // TODO: add this + this.rand = new EaglercraftRandom(parLong1, !worldIn.getWorldInfo().isOldEaglercraftRandom()); + this.lperlinNoise1 = new NoiseGeneratorOctaves(this.rand, 16); + this.lperlinNoise2 = new NoiseGeneratorOctaves(this.rand, 16); + this.perlinNoise1 = new NoiseGeneratorOctaves(this.rand, 8); + this.noiseGen5 = new NoiseGeneratorOctaves(this.rand, 10); + this.noiseGen6 = new NoiseGeneratorOctaves(this.rand, 16); + this.islandNoise = new NoiseGeneratorSimplex(this.rand); } public void func_180520_a(int parInt1, int parInt2, ChunkPrimer parChunkPrimer) { - byte b0 = 2; - int i = b0 + 1; - byte b1 = 33; - int j = b0 + 1; - this.densities = this.initializeNoiseField(this.densities, parInt1 * b0, 0, parInt2 * b0, i, b1, j); + int i = 2; + int j = i + 1; + int k = 33; + int l = i + 1; + this.buffer = this.initializeNoiseField(this.buffer, parInt1 * i, 0, parInt2 * i, j, k, l); - for (int k = 0; k < b0; ++k) { - for (int l = 0; l < b0; ++l) { - for (int i1 = 0; i1 < 32; ++i1) { + for (int i1 = 0; i1 < i; ++i1) { + for (int j1 = 0; j1 < i; ++j1) { + for (int k1 = 0; k1 < 32; ++k1) { double d0 = 0.25D; - double d1 = this.densities[((k + 0) * j + l + 0) * b1 + i1 + 0]; - double d2 = this.densities[((k + 0) * j + l + 1) * b1 + i1 + 0]; - double d3 = this.densities[((k + 1) * j + l + 0) * b1 + i1 + 0]; - double d4 = this.densities[((k + 1) * j + l + 1) * b1 + i1 + 0]; - double d5 = (this.densities[((k + 0) * j + l + 0) * b1 + i1 + 1] - d1) * d0; - double d6 = (this.densities[((k + 0) * j + l + 1) * b1 + i1 + 1] - d2) * d0; - double d7 = (this.densities[((k + 1) * j + l + 0) * b1 + i1 + 1] - d3) * d0; - double d8 = (this.densities[((k + 1) * j + l + 1) * b1 + i1 + 1] - d4) * d0; + double d1 = this.buffer[((i1 + 0) * l + j1 + 0) * k + k1 + 0]; + double d2 = this.buffer[((i1 + 0) * l + j1 + 1) * k + k1 + 0]; + double d3 = this.buffer[((i1 + 1) * l + j1 + 0) * k + k1 + 0]; + double d4 = this.buffer[((i1 + 1) * l + j1 + 1) * k + k1 + 0]; + double d5 = (this.buffer[((i1 + 0) * l + j1 + 0) * k + k1 + 1] - d1) * d0; + double d6 = (this.buffer[((i1 + 0) * l + j1 + 1) * k + k1 + 1] - d2) * d0; + double d7 = (this.buffer[((i1 + 1) * l + j1 + 0) * k + k1 + 1] - d3) * d0; + double d8 = (this.buffer[((i1 + 1) * l + j1 + 1) * k + k1 + 1] - d4) * d0; - for (int j1 = 0; j1 < 4; ++j1) { + for (int l1 = 0; l1 < 4; ++l1) { double d9 = 0.125D; double d10 = d1; double d11 = d2; double d12 = (d3 - d1) * d9; double d13 = (d4 - d2) * d9; - for (int k1 = 0; k1 < 8; ++k1) { + for (int i2 = 0; i2 < 8; ++i2) { double d14 = 0.125D; double d15 = d10; double d16 = (d11 - d10) * d14; - for (int l1 = 0; l1 < 8; ++l1) { - IBlockState iblockstate = null; + for (int j2 = 0; j2 < 8; ++j2) { + IBlockState iblockstate = AIR; + if (d15 > 0.0D) { - iblockstate = Blocks.end_stone.getDefaultState(); + iblockstate = END_STONE; } - int i2 = k1 + k * 8; - int j2 = j1 + i1 * 4; - int k2 = l1 + l * 8; - parChunkPrimer.setBlockState(i2, j2, k2, iblockstate); + int k2 = i2 + i1 * 8; + int l2 = l1 + k1 * 4; + int i3 = j2 + j1 * 8; + parChunkPrimer.setBlockState(k2, l2, i3, iblockstate); d15 += d16; } @@ -128,37 +142,38 @@ public class ChunkProviderEnd implements IChunkProvider { } } } - } public void func_180519_a(ChunkPrimer parChunkPrimer) { for (int i = 0; i < 16; ++i) { for (int j = 0; j < 16; ++j) { - byte b0 = 1; - int k = -1; - IBlockState iblockstate = Blocks.end_stone.getDefaultState(); - IBlockState iblockstate1 = Blocks.end_stone.getDefaultState(); + int k = 1; + int l = -1; + IBlockState iblockstate = END_STONE; + IBlockState iblockstate1 = END_STONE; + + for (int i1 = 127; i1 >= 0; --i1) { + IBlockState iblockstate2 = parChunkPrimer.getBlockState(i, i1, j); - for (int l = 127; l >= 0; --l) { - IBlockState iblockstate2 = parChunkPrimer.getBlockState(i, l, j); if (iblockstate2.getBlock().getMaterial() == Material.air) { - k = -1; + l = -1; } else if (iblockstate2.getBlock() == Blocks.stone) { - if (k == -1) { - if (b0 <= 0) { - iblockstate = Blocks.air.getDefaultState(); - iblockstate1 = Blocks.end_stone.getDefaultState(); + if (l == -1) { + if (k <= 0) { + iblockstate = AIR; + iblockstate1 = END_STONE; } - k = b0; - if (l >= 0) { - parChunkPrimer.setBlockState(i, l, j, iblockstate); + l = k; + + if (i1 >= 0) { + parChunkPrimer.setBlockState(i, i1, j, iblockstate); } else { - parChunkPrimer.setBlockState(i, l, j, iblockstate1); + parChunkPrimer.setBlockState(i, i1, j, iblockstate1); } - } else if (k > 0) { - --k; - parChunkPrimer.setBlockState(i, l, j, iblockstate1); + } else if (l > 0) { + --l; + parChunkPrimer.setBlockState(i, i1, j, iblockstate1); } } } @@ -173,14 +188,19 @@ public class ChunkProviderEnd implements IChunkProvider { * MP client it will generates all the blocks for the specified * chunk from the map seed and chunk seed */ - public Chunk provideChunk(int i, int j) { - this.endRNG.setSeed((long) i * 341873128712L + (long) j * 132897987541L); + public Chunk provideChunk(int x, int z) { + this.rand.setSeed((long) x * 341873128712L + (long) z * 132897987541L); ChunkPrimer chunkprimer = new ChunkPrimer(); - this.biomesForGeneration = this.endWorld.getWorldChunkManager().loadBlockGeneratorData(this.biomesForGeneration, - i * 16, j * 16, 16, 16); - this.func_180520_a(i, j, chunkprimer); + this.biomesForGeneration = this.worldObj.getWorldChunkManager().loadBlockGeneratorData(this.biomesForGeneration, + x * 16, z * 16, 16, 16); + this.func_180520_a(x, z, chunkprimer); this.func_180519_a(chunkprimer); - Chunk chunk = new Chunk(this.endWorld, chunkprimer, i, j); + + if (this.mapFeaturesEnabled) { + // this.endCityGen.generate(this.worldObj, x, z, chunkprimer); + } + + Chunk chunk = new Chunk(this.worldObj, chunkprimer, x, z); byte[] abyte = chunk.getBiomeArray(); for (int k = 0; k < abyte.length; ++k) { @@ -195,51 +215,90 @@ public class ChunkProviderEnd implements IChunkProvider { return this.provideChunk(parInt1, parInt2); } + private float getIslandHeightValue(int p_185960_1_, int p_185960_2_, int p_185960_3_, int p_185960_4_) { + float f = (float) (p_185960_1_ * 2 + p_185960_3_); + float f1 = (float) (p_185960_2_ * 2 + p_185960_4_); + float f2 = 100.0F - MathHelper.sqrt_float(f * f + f1 * f1) * 8.0F; + + if (f2 > 80.0F) { + f2 = 80.0F; + } + + if (f2 < -100.0F) { + f2 = -100.0F; + } + + for (int i = -12; i <= 12; ++i) { + for (int j = -12; j <= 12; ++j) { + long k = (long) (p_185960_1_ + i); + long l = (long) (p_185960_2_ + j); + + if (k * k + l * l > 4096L + && this.islandNoise.func_151605_a((double) k, (double) l) < -0.8999999761581421D) { + float f3 = (MathHelper.abs((float) k) * 3439.0F + MathHelper.abs((float) l) * 147.0F) % 13.0F + + 9.0F; + f = (float) (p_185960_3_ - i * 2); + f1 = (float) (p_185960_4_ - j * 2); + float f4 = 100.0F - MathHelper.sqrt_float(f * f + f1 * f1) * f3; + + if (f4 > 80.0F) { + f4 = 80.0F; + } + + if (f4 < -100.0F) { + f4 = -100.0F; + } + + if (f4 > f2) { + f2 = f4; + } + } + } + } + + return f2; + } + + public boolean isIslandChunk(int p_185961_1_, int p_185961_2_) { + return (long) p_185961_1_ * (long) p_185961_1_ + (long) p_185961_2_ * (long) p_185961_2_ > 4096L + && this.getIslandHeightValue(p_185961_1_, p_185961_2_, 1, 1) >= 0.0F; + } + /** * + * generates a subset of the level's terrain data. Takes 7 * arguments: the [empty] noise array, the position, and the * size. */ - private double[] initializeNoiseField(double[] parArrayOfDouble, int parInt1, int parInt2, int parInt3, int parInt4, - int parInt5, int parInt6) { - if (parArrayOfDouble == null) { - parArrayOfDouble = new double[parInt4 * parInt5 * parInt6]; + private double[] initializeNoiseField(double[] p_185963_1_, int p_185963_2_, int p_185963_3_, int p_185963_4_, + int p_185963_5_, int p_185963_6_, int p_185963_7_) { + if (p_185963_1_ == null) { + p_185963_1_ = new double[p_185963_5_ * p_185963_6_ * p_185963_7_]; } double d0 = 684.412D; double d1 = 684.412D; - this.noiseData4 = this.noiseGen4.generateNoiseOctaves(this.noiseData4, parInt1, parInt3, parInt4, parInt6, - 1.121D, 1.121D, 0.5D); - this.noiseData5 = this.noiseGen5.generateNoiseOctaves(this.noiseData5, parInt1, parInt3, parInt4, parInt6, - 200.0D, 200.0D, 0.5D); d0 = d0 * 2.0D; - this.noiseData1 = this.noiseGen3.generateNoiseOctaves(this.noiseData1, parInt1, parInt2, parInt3, parInt4, - parInt5, parInt6, d0 / 80.0D, d1 / 160.0D, d0 / 80.0D); - this.noiseData2 = this.noiseGen1.generateNoiseOctaves(this.noiseData2, parInt1, parInt2, parInt3, parInt4, - parInt5, parInt6, d0, d1, d0); - this.noiseData3 = this.noiseGen2.generateNoiseOctaves(this.noiseData3, parInt1, parInt2, parInt3, parInt4, - parInt5, parInt6, d0, d1, d0); - int i = 0; + this.pnr = this.perlinNoise1.generateNoiseOctaves(this.pnr, p_185963_2_, p_185963_3_, p_185963_4_, p_185963_5_, + p_185963_6_, p_185963_7_, d0 / 80.0D, d1 / 160.0D, d0 / 80.0D); + this.ar = this.lperlinNoise1.generateNoiseOctaves(this.ar, p_185963_2_, p_185963_3_, p_185963_4_, p_185963_5_, + p_185963_6_, p_185963_7_, d0, d1, d0); + this.br = this.lperlinNoise2.generateNoiseOctaves(this.br, p_185963_2_, p_185963_3_, p_185963_4_, p_185963_5_, + p_185963_6_, p_185963_7_, d0, d1, d0); + int i = p_185963_2_ / 2; + int j = p_185963_4_ / 2; + int k = 0; - for (int j = 0; j < parInt4; ++j) { - for (int k = 0; k < parInt6; ++k) { - float f = (float) (j + parInt1) / 1.0F; - float f1 = (float) (k + parInt3) / 1.0F; - float f2 = 100.0F - MathHelper.sqrt_float(f * f + f1 * f1) * 8.0F; - if (f2 > 80.0F) { - f2 = 80.0F; - } + for (int l = 0; l < p_185963_5_; ++l) { + for (int i1 = 0; i1 < p_185963_7_; ++i1) { + float f = this.getIslandHeightValue(i, j, l, i1); - if (f2 < -100.0F) { - f2 = -100.0F; - } - - for (int l = 0; l < parInt5; ++l) { + for (int j1 = 0; j1 < p_185963_6_; ++j1) { double d2 = 0.0D; - double d3 = this.noiseData2[i] / 512.0D; - double d4 = this.noiseData3[i] / 512.0D; - double d5 = (this.noiseData1[i] / 10.0D + 1.0D) / 2.0D; + double d3 = this.ar[k] / 512.0D; + double d4 = this.br[k] / 512.0D; + double d5 = (this.pnr[k] / 10.0D + 1.0D) / 2.0D; + if (d5 < 0.0D) { d2 = d3; } else if (d5 > 1.0D) { @@ -249,27 +308,29 @@ public class ChunkProviderEnd implements IChunkProvider { } d2 = d2 - 8.0D; - d2 = d2 + (double) f2; - byte b0 = 2; - if (l > parInt5 / 2 - b0) { - double d6 = (double) ((float) (l - (parInt5 / 2 - b0)) / 64.0F); + d2 = d2 + (double) f; + int k1 = 2; + + if (j1 > p_185963_6_ / 2 - k1) { + double d6 = (double) ((float) (j1 - (p_185963_6_ / 2 - k1)) / 64.0F); d6 = MathHelper.clamp_double(d6, 0.0D, 1.0D); d2 = d2 * (1.0D - d6) + -3000.0D * d6; } - b0 = 8; - if (l < b0) { - double d7 = (double) ((float) (b0 - l) / ((float) b0 - 1.0F)); + k1 = 8; + + if (j1 < k1) { + double d7 = (double) ((float) (k1 - j1) / ((float) k1 - 1.0F)); d2 = d2 * (1.0D - d7) + -30.0D * d7; } - parArrayOfDouble[i] = d2; - ++i; + p_185963_1_[k] = d2; + ++k; } } } - return parArrayOfDouble; + return p_185963_1_; } /** @@ -284,12 +345,56 @@ public class ChunkProviderEnd implements IChunkProvider { * + * Populates chunk with ores etc etc */ - public void populate(IChunkProvider var1, int i, int j) { + public void populate(IChunkProvider var1, int x, int z) { BlockFalling.fallInstantly = true; - BlockPos blockpos = new BlockPos(i * 16, 0, j * 16); - this.endWorld.getBiomeGenForCoords(blockpos.add(16, 0, 16)).decorate(this.endWorld, this.endWorld.rand, - blockpos); - BlockFalling.fallInstantly = false; + BlockPos blockpos = new BlockPos(x * 16, 0, z * 16); + + if (this.mapFeaturesEnabled) + { + // this.endCityGen.generateStructure(this.worldObj, this.rand, new ChunkPos(x, z)); + } + + this.worldObj.getBiomeGenForCoords(blockpos.add(16, 0, 16)).decorate(this.worldObj, this.worldObj.rand, blockpos); + long i = (long)x * (long)x + (long)z * (long)z; + + if (i > 4096L) + { + float f = this.getIslandHeightValue(x, z, 1, 1); + + if (f < -20.0F && this.rand.nextInt(14) == 0) + { + this.endIslands.generate(this.worldObj, this.rand, blockpos.add(this.rand.nextInt(16) + 8, 55 + this.rand.nextInt(16), this.rand.nextInt(16) + 8)); + + if (this.rand.nextInt(4) == 0) + { + this.endIslands.generate(this.worldObj, this.rand, blockpos.add(this.rand.nextInt(16) + 8, 55 + this.rand.nextInt(16), this.rand.nextInt(16) + 8)); + } + } + + if (this.getIslandHeightValue(x, z, 1, 1) > 40.0F) + { + int j = this.rand.nextInt(5); + + for (int k = 0; k < j; ++k) + { + int l = this.rand.nextInt(16) + 8; + int i1 = this.rand.nextInt(16) + 8; + int j1 = this.worldObj.getHeight(blockpos.add(l, 0, i1)).getY(); + + if (j1 > 0) + { + int k1 = j1 - 1; + + if (this.worldObj.isAirBlock(blockpos.add(l, k1 + 1, i1)) && this.worldObj.getBlockState(blockpos.add(l, k1, i1)).getBlock() == Blocks.end_stone) + { + BlockChorusFlower.generatePlant(this.worldObj, blockpos.add(l, k1 + 1, i1), this.rand, 8); + } + } + } + } + } + + BlockFalling.fallInstantly = false; } public boolean func_177460_a(IChunkProvider var1, Chunk var2, int var3, int var4) { @@ -342,7 +447,7 @@ public class ChunkProviderEnd implements IChunkProvider { public List getPossibleCreatures(EnumCreatureType enumcreaturetype, BlockPos blockpos) { - return this.endWorld.getBiomeGenForCoords(blockpos).getSpawnableList(enumcreaturetype); + return this.worldObj.getBiomeGenForCoords(blockpos).getSpawnableList(enumcreaturetype); } public BlockPos getStrongholdGen(World var1, String var2, BlockPos var3) { diff --git a/src/game/java/net/minecraft/world/gen/feature/WorldGenEndIsland.java b/src/game/java/net/minecraft/world/gen/feature/WorldGenEndIsland.java new file mode 100644 index 0000000..67de342 --- /dev/null +++ b/src/game/java/net/minecraft/world/gen/feature/WorldGenEndIsland.java @@ -0,0 +1,33 @@ +package net.minecraft.world.gen.feature; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +public class WorldGenEndIsland extends WorldGenerator +{ + public boolean generate(World worldIn, EaglercraftRandom rand, BlockPos position) + { + float f = (float)(rand.nextInt(3) + 4); + + for (int i = 0; f > 0.5F; --i) + { + for (int j = MathHelper.floor_float(-f); j <= MathHelper.ceiling_float_int(f); ++j) + { + for (int k = MathHelper.floor_float(-f); k <= MathHelper.ceiling_float_int(f); ++k) + { + if ((float)(j * j + k * k) <= (f + 1.0F) * (f + 1.0F)) + { + this.setBlockAndNotifyAdequately(worldIn, position.add(j, i, k), Blocks.end_stone.getDefaultState()); + } + } + } + + f = (float)((double)f - ((double)rand.nextInt(2) + 0.5D)); + } + + return true; + } +} diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java index 085de7e..64974b7 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java @@ -61,6 +61,15 @@ public class PlatformAssets { } } + public static List listFilesAtPath(String path) { + List ret = new ArrayList<>(); + File f = new File("resources", path); + if(f.isDirectory()) { + listFilesAtPath(f, ret, path); + } + return ret; + } + public static ImageData loadImageFile(InputStream data) { return loadImageFile(data, "image/png"); } diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java index 6ce6659..440ca82 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java @@ -313,6 +313,8 @@ public class PlatformRuntime { GLES30.glEnable(KHRDebug.GL_DEBUG_OUTPUT_KHR); GLES30.glEnable(KHRDebug.GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); + + ServerAssets.initialize(); logger.info("Initializing Audio..."); PlatformAudio.platformInitialize(); diff --git a/src/main/java/net/hoosiertransfer/ServerAssets.java b/src/main/java/net/hoosiertransfer/ServerAssets.java new file mode 100644 index 0000000..fbebd68 --- /dev/null +++ b/src/main/java/net/hoosiertransfer/ServerAssets.java @@ -0,0 +1,53 @@ +package net.hoosiertransfer; + +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import java.io.InputStream; +import java.io.ByteArrayInputStream; + +import net.lax1dude.eaglercraft.v1_8.internal.PlatformAssets; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController; +import net.lax1dude.eaglercraft.v1_8.sp.ipc.IPCPacket1DUploadServerAsset; + +public class ServerAssets { + public static final Logger logger = LogManager.getLogger("ServerAssets"); + private static Map serverAssets = new HashMap<>(); + private static List filenamesForClient = new ArrayList<>(); + + // ! I might want to call initialize when the server starts up instead of when the client starts up + public static void initialize() { + filenamesForClient = PlatformAssets.listFilesAtPath("assets/minecraft/server"); + } + + public static void sendAssetsToServer() { + for (String path : filenamesForClient) { + byte[] data = PlatformAssets.getResourceBytes(path); + if (data != null) { + logger.info("Uploading asset: " + path); + SingleplayerServerController.sendIPCPacket(new IPCPacket1DUploadServerAsset(path, data)); + } + } + } + + public static void uploadAsset(String path, byte[] data) { + serverAssets.put(path, data); + logger.info("Uploaded asset: " + path); + } + + public static byte[] getAssetBytes(String path) { + return serverAssets.get(path); + } + + public static InputStream getAssetStream(String path) { + byte[] data = serverAssets.get(path); + if (data != null) { + return new ByteArrayInputStream(data); + } else { + return null; + } + } +} diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java index 501a1a7..4e4c7d7 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.function.Consumer; import net.hoosiertransfer.EaglerLUpdateThread; +import net.hoosiertransfer.ServerAssets; import net.lax1dude.eaglercraft.v1_8.internal.EaglerMissingResourceException; import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformANGLE; import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformAgent; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SingleplayerServerController.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SingleplayerServerController.java index ef490a2..90aa90f 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SingleplayerServerController.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SingleplayerServerController.java @@ -13,6 +13,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC; import org.apache.commons.lang3.StringUtils; +import net.hoosiertransfer.ServerAssets; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState; import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData; @@ -314,6 +315,7 @@ public class SingleplayerServerController implements ISaveFormat { switch(pkt.ack) { case 0xFF: logger.info("Integrated server signaled a successful boot"); + ServerAssets.sendAssetsToServer(); sendIPCPacket(new IPCPacket14StringList(IPCPacket14StringList.LOCALE, StringTranslate.dump())); statusState = IntegratedServerState.WORLD_NONE; break; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/ipc/IPCPacket1DUploadServerAsset.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/ipc/IPCPacket1DUploadServerAsset.java new file mode 100644 index 0000000..1fbcb4d --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/ipc/IPCPacket1DUploadServerAsset.java @@ -0,0 +1,61 @@ +package net.lax1dude.eaglercraft.v1_8.sp.ipc; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * Copyright (c) 2023-2024 lax1dude. All Rights Reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +public class IPCPacket1DUploadServerAsset implements IPCPacketBase { + + public static final int ID = 0x1D; + + public String path; + public byte[] data; + + public IPCPacket1DUploadServerAsset() { + } + + public IPCPacket1DUploadServerAsset(String path, byte[] data) { + this.path = path; + this.data = data; + } + + @Override + public void deserialize(DataInput bin) throws IOException { + path = bin.readUTF(); + data = new byte[bin.readInt()]; + bin.readFully(data); + } + + @Override + public void serialize(DataOutput bin) throws IOException { + bin.writeUTF(path); + bin.writeInt(data.length); + bin.write(data); + } + + @Override + public int id() { + return ID; + } + + @Override + public int size() { + return IPCPacketBase.strLen(path) + 4 + data.length; + } + +} diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/ipc/IPCPacketManager.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/ipc/IPCPacketManager.java index 6363efa..ef89611 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/ipc/IPCPacketManager.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/ipc/IPCPacketManager.java @@ -58,6 +58,7 @@ public class IPCPacketManager { mappings.put(IPCPacket1ALoggerMessage.ID, IPCPacket1ALoggerMessage::new); mappings.put(IPCPacket1BEnableLogging.ID, IPCPacket1BEnableLogging::new); mappings.put(IPCPacket1CIssueDetected.ID, IPCPacket1CIssueDetected::new); + mappings.put(IPCPacket1DUploadServerAsset.ID, IPCPacket1DUploadServerAsset::new); mappings.put(IPCPacketFFProcessKeepAlive.ID, IPCPacketFFProcessKeepAlive::new); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java index 0aad61c..ff392cc 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java @@ -9,6 +9,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import net.hoosiertransfer.ServerAssets; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EagUtils; import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData; @@ -395,6 +396,16 @@ public class EaglerIntegratedServerWorker { enableLoggingRedirector(((IPCPacket1BEnableLogging)ipc).enable); break; } + case IPCPacket1DUploadServerAsset.ID: { + IPCPacket1DUploadServerAsset pkt = (IPCPacket1DUploadServerAsset)ipc; + if(!isServerStopped()) { + ServerAssets.uploadAsset(pkt.path, pkt.data); + }else { + logger.error("Client tried to upload asset while server was stopped"); + sendTaskFailed(); + } + break; + } default: logger.error("IPC packet type 0x{} class \"{}\" was not handled", Integer.toHexString(id), ipc.getClass().getSimpleName()); sendTaskFailed(); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java index 7f99536..3ae91ff 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java @@ -6,6 +6,7 @@ import java.util.List; import com.google.common.collect.Lists; +import net.hoosiertransfer.ServerAssets; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java index 96b6774..75416f5 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java @@ -3,6 +3,8 @@ package net.lax1dude.eaglercraft.v1_8.internal; import java.io.InputStream; import java.util.HashMap; import java.util.Map; +import java.util.List; +import java.util.ArrayList; import org.teavm.interop.Async; import org.teavm.interop.AsyncCallback; @@ -90,6 +92,16 @@ public class PlatformAssets { return data == MISSING_FILE ? null : data; } } + + public static List listFilesAtPath(String path) { + List ret = new ArrayList<>(); + for(String s : assets.keySet()) { + if(s.startsWith(path)) { + ret.add(s); + } + } + return ret; + } public static ImageData loadImageFile(InputStream data) { return loadImageFile(data, "image/png"); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java index 2d0d010..92d6eff 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Set; import java.util.function.Consumer; +import net.hoosiertransfer.ServerAssets; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EagUtils; import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; @@ -444,6 +445,8 @@ public class PlatformRuntime { logger.info("Loaded {} resources from EPKs", PlatformAssets.assets.size()); + ServerAssets.initialize(); + if(allowBootMenu && BootMenuEntryPoint.checkShouldLaunchFlag(win)) { logger.info("Boot menu enable flag is set, entering boot menu..."); enterBootMenu();