mirror of
https://github.com/PaperMC/Paper.git
synced 2025-02-18 19:24:10 +01:00
Optimize BlockStateList/BlockData
Mojang included some sanity checks on arguments passed to the BlockData. This code results in the Hash look up occuring twice per call, one to test if it exists and another to retrieve the result. This code should ideally never be hit, unless mojang released a bad build. We can discover bugs with this as furthur code that never expects a null would then NPE, so it would not result in hidden issues. This is super hot code, so removing those checks should give decent gains.
This commit is contained in:
parent
11a3044c3c
commit
80dcb6c4a3
2 changed files with 374 additions and 0 deletions
Spigot-Server-Patches
|
@ -0,0 +1,43 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 18 Mar 2016 19:15:44 -0400
|
||||
Subject: [PATCH] Optimize BlockStateList/BlockData
|
||||
|
||||
Mojang included some sanity checks on arguments passed to the BlockData.
|
||||
This code results in the Hash look up occuring twice per call, one to test if it exists
|
||||
and another to retrieve the result.
|
||||
|
||||
This code should ideally never be hit, unless mojang released a bad build. We can discover bugs with this as furthur code that never expects a null
|
||||
would then NPE, so it would not result in hidden issues.
|
||||
|
||||
This is super hot code, so removing those checks should give decent gains.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockStateList.java b/src/main/java/net/minecraft/server/BlockStateList.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockStateList.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockStateList.java
|
||||
@@ -0,0 +0,0 @@ public class BlockStateList {
|
||||
}
|
||||
|
||||
public <T extends Comparable<T>> T get(IBlockState<T> iblockstate) {
|
||||
- if (!this.b.containsKey(iblockstate)) {
|
||||
- throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.a.t());
|
||||
- } else {
|
||||
- return iblockstate.b().cast(this.b.get(iblockstate));
|
||||
- }
|
||||
+ return iblockstate.b().cast(this.b.get(iblockstate)); // Paper
|
||||
}
|
||||
|
||||
public <T extends Comparable<T>, V extends T> IBlockData set(IBlockState<T> iblockstate, V v0) {
|
||||
- if (!this.b.containsKey(iblockstate)) {
|
||||
- throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.a.t());
|
||||
- } else if (!iblockstate.c().contains(v0)) {
|
||||
- throw new IllegalArgumentException("Cannot set property " + iblockstate + " to " + v0 + " on block " + Block.REGISTRY.b(this.a) + ", it is not an allowed value");
|
||||
- } else {
|
||||
- return (IBlockData) (this.b.get(iblockstate) == v0 ? this : (IBlockData) this.c.get(iblockstate, v0));
|
||||
- }
|
||||
+ return this.b.get(iblockstate) == v0 ? this : this.c.get(iblockstate, v0); // Paper
|
||||
}
|
||||
|
||||
public ImmutableMap<IBlockState<?>, Comparable<?>> s() {
|
||||
--
|
|
@ -1986,6 +1986,337 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockStateList.java b/src/main/java/net/minecraft/server/BlockStateList.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/minecraft/server/BlockStateList.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package net.minecraft.server;
|
||||
+
|
||||
+import com.google.common.base.Function;
|
||||
+import com.google.common.base.Objects;
|
||||
+import com.google.common.collect.HashBasedTable;
|
||||
+import com.google.common.collect.ImmutableCollection;
|
||||
+import com.google.common.collect.ImmutableList;
|
||||
+import com.google.common.collect.ImmutableMap;
|
||||
+import com.google.common.collect.ImmutableSortedMap;
|
||||
+import com.google.common.collect.ImmutableTable;
|
||||
+import com.google.common.collect.Iterables;
|
||||
+import com.google.common.collect.Lists;
|
||||
+import com.google.common.collect.Maps;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collection;
|
||||
+import java.util.Collections;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.LinkedHashMap;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.Map.Entry;
|
||||
+import java.util.regex.Pattern;
|
||||
+
|
||||
+public class BlockStateList {
|
||||
+
|
||||
+ private static final Pattern a = Pattern.compile("^[a-z0-9_]+$");
|
||||
+ private static final Function<IBlockState<?>, String> b = new Function() {
|
||||
+ public String a(IBlockState<?> iblockstate) {
|
||||
+ return iblockstate == null ? "<NULL>" : iblockstate.a();
|
||||
+ }
|
||||
+
|
||||
+ public Object apply(Object object) {
|
||||
+ return this.a((IBlockState) object);
|
||||
+ }
|
||||
+ };
|
||||
+ private final Block c;
|
||||
+ private final ImmutableSortedMap<String, IBlockState<?>> d;
|
||||
+ private final ImmutableList<IBlockData> e;
|
||||
+
|
||||
+ public BlockStateList(Block block, IBlockState<?>... aiblockstate) {
|
||||
+ this.c = block;
|
||||
+ HashMap hashmap = Maps.newHashMap();
|
||||
+ IBlockState[] aiblockstate1 = aiblockstate;
|
||||
+ int i = aiblockstate.length;
|
||||
+
|
||||
+ for (int j = 0; j < i; ++j) {
|
||||
+ IBlockState iblockstate = aiblockstate1[j];
|
||||
+
|
||||
+ a(block, iblockstate);
|
||||
+ hashmap.put(iblockstate.a(), iblockstate);
|
||||
+ }
|
||||
+
|
||||
+ this.d = ImmutableSortedMap.copyOf(hashmap);
|
||||
+ LinkedHashMap linkedhashmap = Maps.newLinkedHashMap();
|
||||
+ ArrayList arraylist = Lists.newArrayList();
|
||||
+ Iterable iterable = IteratorUtils.a(this.e());
|
||||
+ Iterator iterator = iterable.iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ List list = (List) iterator.next();
|
||||
+ Map map = MapGeneratorUtils.b(this.d.values(), list);
|
||||
+ BlockStateList.BlockData blockstatelist_blockdata = new BlockStateList.BlockData(block, ImmutableMap.copyOf(map), null);
|
||||
+
|
||||
+ linkedhashmap.put(map, blockstatelist_blockdata);
|
||||
+ arraylist.add(blockstatelist_blockdata);
|
||||
+ }
|
||||
+
|
||||
+ iterator = arraylist.iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ BlockStateList.BlockData blockstatelist_blockdata1 = (BlockStateList.BlockData) iterator.next();
|
||||
+
|
||||
+ blockstatelist_blockdata1.a((Map) linkedhashmap);
|
||||
+ }
|
||||
+
|
||||
+ this.e = ImmutableList.copyOf(arraylist);
|
||||
+ }
|
||||
+
|
||||
+ public static <T extends Comparable<T>> String a(Block block, IBlockState<T> iblockstate) {
|
||||
+ String s = iblockstate.a();
|
||||
+
|
||||
+ if (!BlockStateList.a.matcher(s).matches()) {
|
||||
+ throw new IllegalArgumentException("Block: " + block.getClass() + " has invalidly named property: " + s);
|
||||
+ } else {
|
||||
+ for (T t : iblockstate.c()) {
|
||||
+ String s1 = iblockstate.a(t);
|
||||
+
|
||||
+ if (!a.matcher(s1).matches())
|
||||
+ {
|
||||
+ throw new IllegalArgumentException("Block: " + block.getClass() + " has property: " + s + " with invalidly named value: " + s1);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return s;
|
||||
+ }
|
||||
+
|
||||
+ public ImmutableList<IBlockData> a() {
|
||||
+ return this.e;
|
||||
+ }
|
||||
+
|
||||
+ private List<Iterable<Comparable<?>>> e() {
|
||||
+ ArrayList arraylist = Lists.newArrayList();
|
||||
+ ImmutableCollection immutablecollection = this.d.values();
|
||||
+ Iterator iterator = immutablecollection.iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ IBlockState iblockstate = (IBlockState) iterator.next();
|
||||
+
|
||||
+ arraylist.add(iblockstate.c());
|
||||
+ }
|
||||
+
|
||||
+ return arraylist;
|
||||
+ }
|
||||
+
|
||||
+ public IBlockData getBlockData() {
|
||||
+ return (IBlockData) this.e.get(0);
|
||||
+ }
|
||||
+
|
||||
+ public Block getBlock() {
|
||||
+ return this.c;
|
||||
+ }
|
||||
+
|
||||
+ public Collection<IBlockState<?>> d() {
|
||||
+ return this.d.values();
|
||||
+ }
|
||||
+
|
||||
+ public String toString() {
|
||||
+ return Objects.toStringHelper(this).add("block", Block.REGISTRY.b(this.c)).add("properties", Iterables.transform(this.d.values(), BlockStateList.b)).toString();
|
||||
+ }
|
||||
+
|
||||
+ static class BlockData extends BlockDataAbstract {
|
||||
+
|
||||
+ private final Block a;
|
||||
+ private final ImmutableMap<IBlockState<?>, Comparable<?>> b;
|
||||
+ private ImmutableTable<IBlockState<?>, Comparable<?>, IBlockData> c;
|
||||
+
|
||||
+ private BlockData(Block block, ImmutableMap<IBlockState<?>, Comparable<?>> immutablemap) {
|
||||
+ this.a = block;
|
||||
+ this.b = immutablemap;
|
||||
+ }
|
||||
+
|
||||
+ public Collection<IBlockState<?>> r() {
|
||||
+ return Collections.unmodifiableCollection(this.b.keySet());
|
||||
+ }
|
||||
+
|
||||
+ public <T extends Comparable<T>> T get(IBlockState<T> iblockstate) {
|
||||
+ if (!this.b.containsKey(iblockstate)) {
|
||||
+ throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.a.t());
|
||||
+ } else {
|
||||
+ return iblockstate.b().cast(this.b.get(iblockstate));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public <T extends Comparable<T>, V extends T> IBlockData set(IBlockState<T> iblockstate, V v0) {
|
||||
+ if (!this.b.containsKey(iblockstate)) {
|
||||
+ throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.a.t());
|
||||
+ } else if (!iblockstate.c().contains(v0)) {
|
||||
+ throw new IllegalArgumentException("Cannot set property " + iblockstate + " to " + v0 + " on block " + Block.REGISTRY.b(this.a) + ", it is not an allowed value");
|
||||
+ } else {
|
||||
+ return (IBlockData) (this.b.get(iblockstate) == v0 ? this : (IBlockData) this.c.get(iblockstate, v0));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public ImmutableMap<IBlockState<?>, Comparable<?>> s() {
|
||||
+ return this.b;
|
||||
+ }
|
||||
+
|
||||
+ public Block getBlock() {
|
||||
+ return this.a;
|
||||
+ }
|
||||
+
|
||||
+ public boolean equals(Object object) {
|
||||
+ return this == object;
|
||||
+ }
|
||||
+
|
||||
+ public int hashCode() {
|
||||
+ return this.b.hashCode();
|
||||
+ }
|
||||
+
|
||||
+ public void a(Map<Map<IBlockState<?>, Comparable<?>>, BlockStateList.BlockData> map) {
|
||||
+ if (this.c != null) {
|
||||
+ throw new IllegalStateException();
|
||||
+ } else {
|
||||
+ HashBasedTable hashbasedtable = HashBasedTable.create();
|
||||
+ Iterator iterator = this.b.entrySet().iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ Entry entry = (Entry) iterator.next();
|
||||
+ IBlockState iblockstate = (IBlockState) entry.getKey();
|
||||
+ Iterator iterator1 = iblockstate.c().iterator();
|
||||
+
|
||||
+ while (iterator1.hasNext()) {
|
||||
+ Comparable comparable = (Comparable) iterator1.next();
|
||||
+
|
||||
+ if (comparable != entry.getValue()) {
|
||||
+ hashbasedtable.put(iblockstate, comparable, map.get(this.b(iblockstate, comparable)));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.c = ImmutableTable.copyOf(hashbasedtable);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private Map<IBlockState<?>, Comparable<?>> b(IBlockState<?> iblockstate, Comparable<?> comparable) {
|
||||
+ HashMap hashmap = Maps.newHashMap(this.b);
|
||||
+
|
||||
+ hashmap.put(iblockstate, comparable);
|
||||
+ return hashmap;
|
||||
+ }
|
||||
+
|
||||
+ public Material getMaterial() {
|
||||
+ return this.a.q(this);
|
||||
+ }
|
||||
+
|
||||
+ public boolean b() {
|
||||
+ return this.a.l(this);
|
||||
+ }
|
||||
+
|
||||
+ public int c() {
|
||||
+ return this.a.m(this);
|
||||
+ }
|
||||
+
|
||||
+ public int d() {
|
||||
+ return this.a.o(this);
|
||||
+ }
|
||||
+
|
||||
+ public boolean f() {
|
||||
+ return this.a.p(this);
|
||||
+ }
|
||||
+
|
||||
+ public MaterialMapColor g() {
|
||||
+ return this.a.r(this);
|
||||
+ }
|
||||
+
|
||||
+ public IBlockData a(EnumBlockRotation enumblockrotation) {
|
||||
+ return this.a.a((IBlockData) this, enumblockrotation);
|
||||
+ }
|
||||
+
|
||||
+ public IBlockData a(EnumBlockMirror enumblockmirror) {
|
||||
+ return this.a.a((IBlockData) this, enumblockmirror);
|
||||
+ }
|
||||
+
|
||||
+ public boolean h() {
|
||||
+ return this.a.c((IBlockData) this);
|
||||
+ }
|
||||
+
|
||||
+ public EnumRenderType i() {
|
||||
+ return this.a.a((IBlockData) this);
|
||||
+ }
|
||||
+
|
||||
+ public boolean k() {
|
||||
+ return this.a.s(this);
|
||||
+ }
|
||||
+
|
||||
+ public boolean l() {
|
||||
+ return this.a.isOccluding(this);
|
||||
+ }
|
||||
+
|
||||
+ public boolean m() {
|
||||
+ return this.a.isPowerSource(this);
|
||||
+ }
|
||||
+
|
||||
+ public int a(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) {
|
||||
+ return this.a.b((IBlockData) this, iblockaccess, blockposition, enumdirection);
|
||||
+ }
|
||||
+
|
||||
+ public boolean n() {
|
||||
+ return this.a.isComplexRedstone(this);
|
||||
+ }
|
||||
+
|
||||
+ public int a(World world, BlockPosition blockposition) {
|
||||
+ return this.a.d(this, world, blockposition);
|
||||
+ }
|
||||
+
|
||||
+ public float b(World world, BlockPosition blockposition) {
|
||||
+ return this.a.b(this, world, blockposition);
|
||||
+ }
|
||||
+
|
||||
+ public float a(EntityHuman entityhuman, World world, BlockPosition blockposition) {
|
||||
+ return this.a.getDamage(this, entityhuman, world, blockposition);
|
||||
+ }
|
||||
+
|
||||
+ public int b(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) {
|
||||
+ return this.a.c(this, iblockaccess, blockposition, enumdirection);
|
||||
+ }
|
||||
+
|
||||
+ public EnumPistonReaction o() {
|
||||
+ return this.a.h(this);
|
||||
+ }
|
||||
+
|
||||
+ public IBlockData b(IBlockAccess iblockaccess, BlockPosition blockposition) {
|
||||
+ return this.a.updateState(this, iblockaccess, blockposition);
|
||||
+ }
|
||||
+
|
||||
+ public boolean p() {
|
||||
+ return this.a.b((IBlockData) this);
|
||||
+ }
|
||||
+
|
||||
+ public AxisAlignedBB d(World world, BlockPosition blockposition) {
|
||||
+ return this.a.a((IBlockData) this, world, blockposition);
|
||||
+ }
|
||||
+
|
||||
+ public void a(World world, BlockPosition blockposition, AxisAlignedBB axisalignedbb, List<AxisAlignedBB> list, Entity entity) {
|
||||
+ this.a.a((IBlockData) this, world, blockposition, axisalignedbb, list, entity);
|
||||
+ }
|
||||
+
|
||||
+ public AxisAlignedBB c(IBlockAccess iblockaccess, BlockPosition blockposition) {
|
||||
+ return this.a.a((IBlockData) this, iblockaccess, blockposition);
|
||||
+ }
|
||||
+
|
||||
+ public MovingObjectPosition a(World world, BlockPosition blockposition, Vec3D vec3d, Vec3D vec3d1) {
|
||||
+ return this.a.a(this, world, blockposition, vec3d, vec3d1);
|
||||
+ }
|
||||
+
|
||||
+ public boolean q() {
|
||||
+ return this.a.k(this);
|
||||
+ }
|
||||
+
|
||||
+ BlockData(Block block, ImmutableMap immutablemap, Object object) {
|
||||
+ this(block, immutablemap);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderFlat.java b/src/main/java/net/minecraft/server/ChunkProviderFlat.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
|
|
Loading…
Add table
Reference in a new issue