- 124
- 1
- 0
делаю железную дорогу. при создании поворота проблемка: блоки рельс с моделью в techne ставятся, но они без текстур. уже перекопал все, что знаю, но проблему решить не смог. вот все файлы, как-то связанные с этими рельсами:
рендер:
блок:
TileEntity (первый раз с ним работаю, почти ничего не понимаю. нужно сохранить угол поворота каждой секции, чтобы при ребуте игры он остался):
класс Rails (для поворота используется SetRotateRail)
маркер (через 2 таких строится поворот):
ну и клиент прокси:
сейчас система должна обрабатывать поворот между маркерами в 3 и 4 положении (потом доделаю остальные). В этой теме мне нужно сделать текстуру и сохранение угла поворота. интересный факт: если поставить поворот, а потом перезайти в игру - текстура будет над головой игрока и когда я сломаю блоки поворота она исчезнет.
рендер:
Код:
public class RenderRail extends TileEntitySpecialRenderer {
private static final ResourceLocation texture = new ResourceLocation("kubictrain:textures/models/Rail.png");
private ModelRail model;
public RenderRail() {
this.model = new ModelRail();
}
@Override
public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float rotate) {
float angle = ClientProxy.tileRail.getAngle(ClientProxy.tileRail.getNBTTagCompound());
if (angle != -1)
{
setRail(tileentity, ClientProxy.tileRail.xCoord, ClientProxy.tileRail.yCoord, ClientProxy.tileRail.zCoord, angle, true);
}
else
{
int i;
if (tileentity.getWorldObj() == null)
{
i = 0;
} else {
Block block = tileentity.getBlockType();
i = tileentity.getBlockMetadata();
if (block != null && i == 0)
{
i = tileentity.getBlockMetadata();
}
}
setRail(tileentity, x, y, z, i, false);
}
}
private void setRail(TileEntity tileentity, double x, double y, double z, float rotate, boolean mode)
{
GL11.glPushMatrix();
GL11.glTranslatef((float) x + 0.5F, (float) y + 1.5F, (float) z + 0.5F);
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
GL11.glPushMatrix();
GL11.glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
if (!mode)
{
int j = 0;
switch ((int) rotate)
{
case 0: j = 360; break;
case 1: j = 90; break;
case 2: j = 180; break;
case 3: j = 270; break;
}
GL11.glRotatef(j, 0.0F, 1.0F, 0F);
}
else
{
GL11.glRotatef(rotate, 0.0F, 1.0F, 0F);
}
this.model.render((Entity)null, 0.0F, 0.0F, -0.1F, 0.0F, 0.0F, 0.0625F);
GL11.glPopMatrix();
GL11.glPopMatrix();
}
}
блок:
Код:
public class Rail extends BlockContainer {
public Rail() {
super(Material.iron);
this.setHardness(3.5F);
this.setResistance(5.0F);
this.setCreativeTab(KubicTrain_Main.kubicTrainMainTab);
this.setBlockName("Rail");
this.setBlockTextureName("kubictrain:Rail");
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.2F, 1.0F);
this.setLightOpacity(0);
}
@Override
public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entity, ItemStack itemStack)
{
int l = MathHelper.floor_double((double)(entity.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
world.setBlockMetadataWithNotify(x, y, z, l, 2);
switch (l)
{
case 0:
world.setBlock(x + 1, y, z, KubicTrain_Main.railBorder);
world.setBlock(x - 1, y, z, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x + 1, y, z, 0, 2);
world.setBlockMetadataWithNotify(x - 1, y, z, 2, 2);
break;
case 1:
world.setBlock(x, y, z + 1, KubicTrain_Main.railBorder);
world.setBlock(x, y, z - 1, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x, y, z + 1, 1, 2);
world.setBlockMetadataWithNotify(x, y, z - 1, 3, 2);
break;
case 2:
world.setBlock(x + 1, y, z, KubicTrain_Main.railBorder);
world.setBlock(x - 1, y, z, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x + 1, y, z, 0, 2);
world.setBlockMetadataWithNotify(x - 1, y, z, 2, 2);
break;
case 3:
world.setBlock(x, y, z + 1, KubicTrain_Main.railBorder);
world.setBlock(x, y, z - 1, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x, y, z + 1, 1, 2);
world.setBlockMetadataWithNotify(x, y, z - 1, 3, 2);
break;
}
}
@Override
public void onBlockDestroyedByPlayer(World world, int x, int y, int z, int meta)
{
try
{
int id = ((Marker) KubicTrain_Main.markerNormal).GetRails(x, y, z);
if (id > -1)
{
((Marker) KubicTrain_Main.markerNormal).DestroyRail(world, id);
}
}
catch (NullPointerException e)
{
switch (meta)
{
case 0:
world.setBlock(x + 1, y, z, Blocks.air);
world.setBlock(x - 1, y, z, Blocks.air);
break;
case 1:
world.setBlock(x, y, z + 1, Blocks.air);
world.setBlock(x, y, z - 1, Blocks.air);
break;
case 2:
world.setBlock(x + 1, y, z, Blocks.air);
world.setBlock(x - 1, y, z, Blocks.air);
break;
case 3:
world.setBlock(x, y, z + 1, Blocks.air);
world.setBlock(x, y, z - 1, Blocks.air);
break;
}
if (hasTileEntity(meta) && !(this instanceof BlockContainer))
{
world.removeTileEntity(x, y, z);
}
System.err.println("Секция не найдена!!!");
}
}
@Override
public void breakBlock(World world, int x, int y, int z, Block block, int meta)
{
if (block == KubicTrain_Main.railBorder)
{
onBlockDestroyedByPlayer(world, x, y, z, meta);
}
else
{
switch (meta)
{
case 0:
world.setBlock(x + 1, y, z, Blocks.air);
world.setBlock(x - 1, y, z, Blocks.air);
break;
case 1:
world.setBlock(x, y, z + 1, Blocks.air);
world.setBlock(x, y, z - 1, Blocks.air);
break;
case 2:
world.setBlock(x + 1, y, z, Blocks.air);
world.setBlock(x - 1, y, z, Blocks.air);
break;
case 3:
world.setBlock(x, y, z + 1, Blocks.air);
world.setBlock(x, y, z - 1, Blocks.air);
break;
}
if (hasTileEntity(meta) && !(this instanceof BlockContainer))
{
world.removeTileEntity(x, y, z);
}
}
}
public int getRenderType()
{
return -1;
}
public boolean isOpaqueCube()
{
return false;
}
public boolean renderAsNomalBlock()
{
return false;
}
@Override
public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) {
return new TileEntityRail();
}
}
TileEntity (первый раз с ним работаю, почти ничего не понимаю. нужно сохранить угол поворота каждой секции, чтобы при ребуте игры он остался):
Код:
public class TileEntityRail extends TileEntity {
private static Map classToNameMap = new HashMap();
private float angle;
private static int railNumber;
private NBTTagCompound nbt;
public TileEntityRail()
{
Func.Print("конструктор тайла");
}
public void addRotate(float a, int id, int x, int y, int z)
{
this.addMapping(getClass(), "KT_rail" + id + "_" + railNumber);
Func.Print("добавляем поворот");
this.nbt = new NBTTagCompound();
this.xCoord = x;
this.yCoord = y;
this.zCoord = z;
this.nbt.setFloat("angle", a);
this.nbt.setInteger("section", id);
this.writeToNBT(nbt);
railNumber++;
}
public void addRail(int id, int x, int y, int z)
{
this.addMapping(getClass(), "KT_rail" + id + "_" + railNumber);
Func.Print("добавляем прямой участок");
this.nbt = new NBTTagCompound();
this.xCoord = x;
this.yCoord = y;
this.zCoord = z;
this.nbt.setFloat("angle", -1);
this.nbt.setInteger("section", id);
this.writeToNBT(nbt);
railNumber++;
}
public void readFromNBT(NBTTagCompound nbt)
{
try {
this.xCoord = nbt.getInteger("x");
this.yCoord = nbt.getInteger("y");
this.zCoord = nbt.getInteger("z");
this.angle = nbt.getFloat("angle");
}
catch (NullPointerException e)
{
Func.Error("неизвестная ошибка!!!");
}
}
public float getAngle(NBTTagCompound nbt)
{
readFromNBT(nbt);
return this.angle;
}
public NBTTagCompound getNBTTagCompound()
{
return this.nbt;
}
}
класс Rails (для поворота используется SetRotateRail)
Код:
public class Rails {
private int id = 0;
private ArrayList <Double> xCoord = new ArrayList <Double> ();
private ArrayList <Double> yCoord = new ArrayList <Double> ();
private ArrayList <Double> zCoord = new ArrayList <Double> ();
private ArrayList <Float> angle = new ArrayList <Float> ();
public Rails() {}
public void AddRail(World world, int x, int y, int z, int meta)
{
world.setBlock(x, y, z, KubicTrain_Main.rail);
ClientProxy.tileRail.addRail(this.id, x, y, z);
world.setBlockMetadataWithNotify(x, y, z, meta, 2);
switch (meta)
{
case 0:
world.setBlock(x + 1, y, z, KubicTrain_Main.railBorder);
world.setBlock(x - 1, y, z, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x + 1, y, z, 0, 2);
world.setBlockMetadataWithNotify(x - 1, y, z, 2, 2);
break;
case 1:
world.setBlock(x, y, z + 1, KubicTrain_Main.railBorder);
world.setBlock(x, y, z - 1, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x, y, z + 1, 1, 2);
world.setBlockMetadataWithNotify(x, y, z - 1, 3, 2);
break;
case 2:
world.setBlock(x + 1, y, z, KubicTrain_Main.railBorder);
world.setBlock(x - 1, y, z, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x + 1, y, z, 0, 2);
world.setBlockMetadataWithNotify(x - 1, y, z, 2, 2);
break;
case 3:
world.setBlock(x, y, z + 1, KubicTrain_Main.railBorder);
world.setBlock(x, y, z - 1, KubicTrain_Main.railBorder);
world.setBlockMetadataWithNotify(x, y, z + 1, 1, 2);
world.setBlockMetadataWithNotify(x, y, z - 1, 3, 2);
break;
}
this.xCoord.add(new Double(x));
this.yCoord.add(new Double(y));
this.zCoord.add(new Double(z));
this.angle.add(null);
this.id++;
}
public void DestroyRail(World world)
{
for (int i = 0; i < this.id; i++)
{
//System.out.println(this.xCoord.get(i).intValue() + " " + this.yCoord.get(i).intValue() + " " + this.zCoord.get(i).intValue());
world.setBlock(this.xCoord.get(i).intValue(), this.yCoord.get(i).intValue(), this.zCoord.get(i).intValue(), Blocks.air);
}
}
public boolean ScanBlocks(int x, int y, int z)
{
for (int i = 0; i < this.id; i++)
{
if ((this.xCoord.get(i).intValue() == x) && (this.yCoord.get(i).intValue() == y) && (this.zCoord.get(i).intValue() == z))
{
return true;
}
}
return false;
}
/**
* установка поворотного участка
* @param world
* первый маркер
* @param x1
* @param y1
* @param z1
* @param meta1
* второй маркер
* @param x2
* @param y2
* @param z2
* @param meta2
*/
public void SetRotateRail(World world, int x1, int y1, int z1, int meta1, int x2, int y2, int z2, int meta2)
{
if (MathFunctions.Module(x1, x2) == MathFunctions.Module(z1, z2) && MathFunctions.Module(y1, y2) == 0
&& meta1 == 3 && meta2 == 4)
{
Func.Print("начало построения поворота");
int xCenter = 0;
int zCenter = 0;
int lenth = MathFunctions.Module(x1, x2);
Func.Print("получение боковой стороны равнобедренного треугольника: " + lenth);
float angle;
switch (meta1)
{
case 3:
xCenter = x1 - lenth;
zCenter = z1;
break;
}
Func.Print("центр: " + xCenter + " " + y1 + " " + zCenter);
angle = (float) (90 / ((Math.sqrt(2) * lenth) - ((Math.sqrt(2) * lenth) % 1) + 1));
Func.Print("получение первоначального угла: " + angle);
Func.Print("основной цикл (" + ((Math.sqrt(2) * lenth) - ((Math.sqrt(2) * lenth) % 1) + 1) + " повторений)");
for (int i = 0; i <= ((Math.sqrt(2) * lenth) - ((Math.sqrt(2) * lenth) % 1) + 1); i++)
{
double xPos = xCenter + (lenth * Math.sin(Math.toRadians(angle * i)));
double zPos = zCenter - (lenth * Math.cos(Math.toRadians(angle * i)));
this.xCoord.add(new Double(xPos));
this.yCoord.add(new Double(y1));
this.zCoord.add(new Double(zPos));
this.angle.add(new Float(angle * i));
Func.Print("координаты: " + xPos + " " + y1 + " " + zPos + "; угол: " + (angle * i));
ClientProxy.tileRail.addRotate(this.angle.get(i).floatValue(), this.id, (int) Math.round(this.xCoord.get(i).doubleValue()), (int) Math.round(this.yCoord.get(i).doubleValue()), (int) Math.round(this.zCoord.get(i).doubleValue()));
world.setBlock((int) Math.round(this.xCoord.get(i).doubleValue()), (int) Math.round(this.yCoord.get(i).doubleValue()), (int) Math.round(this.zCoord.get(i).doubleValue()), KubicTrain_Main.rail);
//world.setBlock((int) Math.round(this.xCoord.get(i).doubleValue()), (int) Math.round(this.yCoord.get(i).doubleValue()), (int) Math.round(this.zCoord.get(i).doubleValue()), Blocks.stone);
this.id++;
}
}
}
}
маркер (через 2 таких строится поворот):
Код:
public class Marker extends Block {
private int mode;
private static int id;
private ArrayList <Rails> rails = new ArrayList <Rails> ();
private Markers marker;
private static boolean side = false;
@SideOnly(Side.CLIENT)
private IIcon icon1;
@SideOnly(Side.CLIENT)
private IIcon icon2;
@SideOnly(Side.CLIENT)
private IIcon icon3;
@SideOnly(Side.CLIENT)
private IIcon icon4;
public Marker(int mode) {
super(Material.iron);
switch (mode)
{
case 1: this.setBlockName("MarkerNormal"); break;
case 2: this.setBlockName("MarkerSwitch"); break;
case 3: this.setBlockName("MarkerClimb"); break;
}
this.setCreativeTab(KubicTrain_Main.kubicTrainMainTab);
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 1.0F);
this.mode = mode;
this.marker = new Markers();
}
@SideOnly(Side.CLIENT)
public IIcon getIcon(int side, int meta)
{
return meta == 5 ? this.icon4 : (meta == 2 ? this.icon3 : (meta == 3 ? this.icon1 : this.icon2));
}
@SideOnly(Side.CLIENT)
public void registerBlockIcons (IIconRegister iconRegister)
{
this.icon1 = iconRegister.registerIcon("kubictrain:MarkerNormal1");
this.icon2 = iconRegister.registerIcon("kubictrain:MarkerNormal2");
this.icon3 = iconRegister.registerIcon("kubictrain:MarkerNormal3");
this.icon4 = iconRegister.registerIcon("kubictrain:MarkerNormal4");
}
@Override
public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entity, ItemStack itemStack) {
this.marker.SetMarker(world, x, y, z, entity);
}
//клик ПКМ по маркеру
public boolean onBlockActivated (World world, int x, int y, int z, EntityPlayer player, int q, float a, float b, float c)
{
int distance = 0; //расстояние до маркера
int mark = this.marker.ActiveMarker(world, x, y, z, 50); //Id ближайшего маркера в радиусе 50 блоков
if (mark >= 0)
{
//получаем координаты ближайшего маркера
int xCoord = this.marker.GetXCoord(mark, player);
int yCoord = this.marker.GetYCoord(mark, player);
int zCoord = this.marker.GetZCoord(mark, player);
//проверяем расположение на одной высоте текущего и ближайшего маркера
if (y == yCoord)
{
Func.Print(world.getBlockMetadata(x, y, z) + " (Meta 1 маркера)");
Func.Print(world.getBlockMetadata(xCoord, yCoord, zCoord) + " (Meta 2 маркера)");
//если координата x одинаковая - записываем расстояние по z
if (x == xCoord)
{
distance = MathFunctions.Module(zCoord, z);
}
//если координата z одинаковая - записываем расстояние по x
else if (z == zCoord)
{
distance = MathFunctions.Module(xCoord, x);
}
//поворот
else if (world.getBlockMetadata(x, y, z) == 3 && world.getBlockMetadata(xCoord, yCoord, zCoord) == 4)
{
Func.Print("Начинаем строить поворот");
this.rails.add(new Rails());
int meta1 = world.getBlockMetadata(x, y, z);
int meta2 = world.getBlockMetadata(xCoord, yCoord, zCoord);
this.marker.DeleteMarker(world, x, y, z);
this.marker.DeleteMarker(world, xCoord, yCoord, zCoord);
this.rails.get(id).SetRotateRail(world, x, y, z, meta1, xCoord, yCoord, zCoord, meta2);
//увеличиваем id, для следующего сектора
id++;
//сообщаем игроку об успешной постройке
side = !side;
if (side) Func.ChatMessage ("Поворот построен!", player);
//возвращаем майну об успешном срабатывании блока
return true;
}
//создаем новый сектор и записываем его в массив
this.rails.add(new Rails());
//получаем мету
int meta = world.getBlockMetadata(x, y, z);
//создаем рельсы
if (distance > 0)
{
this.marker.DeleteMarker(world, x, y, z);
this.marker.DeleteMarker(world, xCoord, yCoord, zCoord);
for (int i = 0; i <= distance; i++) {
switch (meta)
{
case 2:
this.rails.get(id).AddRail(world, x, y, z + i, 2);
break;
case 3:
this.rails.get(id).AddRail(world, x, y, z - i, 2);
break;
case 4:
this.rails.get(id).AddRail(world, x + i, y, z, 1);
break;
case 5:
this.rails.get(id).AddRail(world, x - i, y, z, 1);
break;
}
}
//увеличиваем id, для следующего сектора
id++;
//сообщаем игроку об успешной постройке
side = !side;
if (side) Func.ChatMessage ("Прямой участок построен!", player);
//возвращаем майну об успешном срабатывании блока
return true;
}
}
}
side = !side;
if (side) Func.ChatMessage ("Маркер не найден!!!", player);
return false;
}
public void DestroyRail(World world, int id)
{
this.rails.get(id).DestroyRail(world);
}
public int GetRails(int x, int y, int z)
{
for (int i = 0; i < id; i++){
if (this.rails.get(i).ScanBlocks(x, y, z))
{
return i;
}
}
return -1;
}
@Override
public void onBlockDestroyedByPlayer(World world, int x, int y, int z, int meta)
{
this.marker.DeleteMarker(world, x, y, z);
}
}
ну и клиент прокси:
Код:
public class ClientProxy extends CommonProxy {
public static TileEntityRail tileRail;
public void registerRenderThings() {
TileEntitySpecialRenderer renderRail = new RenderRail();
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRail.class, renderRail);
MinecraftForgeClient.registerItemRenderer(Item.getItemFromBlock(KubicTrain_Main.rail), new ItemRenderRail(renderRail, tileRail = new TileEntityRail()));
}
public void registerTileEntitySpecialRenderer() {
}
}
сейчас система должна обрабатывать поворот между маркерами в 3 и 4 положении (потом доделаю остальные). В этой теме мне нужно сделать текстуру и сохранение угла поворота. интересный факт: если поставить поворот, а потом перезайти в игру - текстура будет над головой игрока и когда я сломаю блоки поворота она исчезнет.