Du möchtest also dein Mod oder den eines anderen für Bukkit verfügbar machen? Dann sei dir bewusst das du bereits viel über das Modding und Java wissen musst, den ich werde nicht erklären wie man von Anfang an eine Mod erstellt, sondern nur eine vorhandene nach Bukkit portet!
Du musst auf jeden Fall wissen wie man eine Mod decompiliert! Wie man Blöcke/Items erstellt, sie mit Funktionen versieht, ganze einfach wie man eine Mod Programmiert!(!!)
Ich empfehle dir dich auch mit der API Forge auseinander zu setzen, den diese erleichtert vieles und im Tutorial arbeite ich teilweise damit. Im Englischen Minecraft Forum findest du dazu 2 Gute Tutorials!
Dann solltest du auch wissen wie man einen Server startet und ihn zum Testen einrichtest.
Kannst du das alles? Dann lies nun weiter! # Vorbereitungen
Hast du alles? Na dann legen wir nun los! (Achtung nur für 1.2.5, die oberen Downloads sind 1.4.2!!)
Als erstes solltest du dir einen Ordner z.b. Meine Mods und in diesem wieder 2 Unterordner erstellen, z.b. MeinMod Bukkit Port, MeinMod MCP. Jetzt packst du dir die craftbukkit-1.2.3-R0.3-MCPC-SNAPSHOT-56.jar, mappings_bukkit_1.2_r4.tar und das Zip Archiv von MCP in den Hauptordner und nartürlich die Mod die du Porten möchtest.
So sollte es dann aussehen:
Gut nun packst du alle Daten vom MCP wie gewohnt in den MeinMod MCP Ordner, fügst alle Server Daten in die minecraft_server.jar ein, wie ModLoaderMp, Forge, die Mod usw. Jetzt aber noch nicht decompilieren sondern die Dateien vom mappings_bukkit_1.2_r4.tar Archiv in den conf Ordner von MCP einfügen, jetzt darfst du decompilieren (Fehler sofern nicht von der Mod selber sind NORMAL).
Jetzt Starte Eclipse und wähle als Workspace den MeinMod Bukkit Port Ordner von vorhin an!
Starte ein neues Java Projekt und erstelle dann in src ein neues Package net.minecraft.server.
Kopiere nun alle Source Daten des Mods (Und nur des Mods!!) in dieses Package! Den Source findest du in \MeinMod MCP\src\minecraft\net\minecraft\src
Klicke nun rechts auf den Projekt Namen und wähle Properties aus. Klicke dann auf der Linken Seite auf Java Build Path, dann auf Libaries und auf Add External Jar, füge nun die craftbukkit-1.2.3-R0.3-MCPC-SNAPSHOT-56.jar ein!
Gut das wars auch schon, klingt schwer aber ist mit Übung in 2 Minuten (ohne decompilieren) erledigt .
Somit ist der Mod nun bereit für Bukkit geportet zu werden!
So sollte dann alles ungefähr aussehen:
package net.minecraft.src;
public class BlockMeinBlock extends Block
{
public BlockMeinBlock (int i, int j)
{
super(i, j, Material.cloth);
setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.065F, 1.0F);
}
public boolean isOpaqueCube()
{
return false;
}
public boolean renderAsNormalBlock()
{
return false;
}
}
Nun in Bukkit:
Code:
package net.minecraft.server;
public class BlockMeinBlock extends Block
{
public BlockMeinBlock (int i, int j)
{
super(i, j, Material.CLOTH);
a(0.0F, 0.0F, 0.0F, 1.0F, 0.065F, 1.0F);
}
public boolean isOpaqueCube()
{
return false;
}
public boolean renderAsNormalBlock()
{
return false;
}
}
setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.065F, 1.0F); = a(0.0F, 0.0F, 0.0F, 1.0F, 0.065F, 1.0F); package net.minecraft.src = package net.minecraft.server 2. Wie Porte ich ein Item
Der Code in mod_MeinMod:
Code:
public static Item MeinItem;
static
{
MeinItem= new ItemMeinItem(3500, 0).setIconIndex(ModLoader.addOverride("/gui/items.png", "/Soup.png")).setItemName("Cooles Item");
}
In Bukkit:
Code:
public static Item MeinItem;
static
{
MeinItem= new Item(3500, 0).setIconIndex(ModLoader.addOverride("/gui/items.png", "/Soup.png")).a("Cooles Item");
}
.setItemName("Cooles Item") = .a("Cooles Item") Zusatz Info für Forge API: .setIconCoord(0, 0) = .a(0,0)
3. Das Thema Crafting Rezepte
Der Code in mod_MeinMod:
Code:
ModLoader.addRecipe(new ItemStack(MeinItem, 1),
new Object[] {"RG", "RG", 'R', new ItemStack(Item.redstone), 'G', new ItemStack(Item.lightStoneDust)});
In Bukkit:
Code:
ModLoader.addRecipe(new ItemStack(MeinItem, 1),
new Object[] {"RG", "RG", Character.valueOf('R'), new ItemStack(Item.REDSTONE), Character.valueOf('G'), new ItemStack(Item.GLOWSTONE_DUST)});
Beachtet das Character.valueOf !!
Achtung ab hier wird nur noch mit Forge Programmiert! 4. Erstellen einer Server Konfiguration für ID's
So da wir ja eine Server Mod erstellen ist eine Konfiguration Datei zum ändern von ID's natürlich Pflicht!
Fangen wir damit an das obere Block Beispiel Konfigurations fähig zu machen
So sieht der Code bisher aus:
Code:
public static Block BeispielBlock;
static
{
BeispielBlock = new BlockMeinBlock(200, ModLoader.addOverride("/terrain.png", "/Block.png")).c(1.0F).a("Cooler Block");
}
Zualler erst fügen wir ein PropsHelperMeinMod.initProps(); nach
Code:
static
{
ein. Ignoriert das gemeckere von Eclipse und erstellt eine neue Klasse namens PropsHelperMeinMod
Fügt folgendes dort hinein:
Code:
package net.minecraft.server;
import java.io.File;
import java.io.IOException;
import forge.Configuration;
public class PropsHelperMeinMod {
public static void initProps()
{
File newFile = new File("config/Mein_Mod_Server.cfg"); //Ändert hier den Pfad und Namen wie es euch gefällt
try
{
newFile.createNewFile();
System.out.println("Successfully created/read configuration file");
}
catch (IOException e)
{
System.out.println("Could not create configuration file for mod_MeinMod. Reason:");
System.out.println(e);
}
Configuration config = new Configuration(newFile);
config.load();
//Erstellung mit einer Standart ID, bei Blöcken
MeinBlockID = Integer.parseInt(config.getOrCreateIntProperty("Block Name in der Datei", Configuration.BLOCK_PROPERTY, 200).value);
//Für ein Item
MeinItemID = Integer.parseInt(config.getOrCreateIntProperty("Item Name in der Datei", Configuration.ITEM_PROPERTY, 3502).value);
config.save();
}
public static int MeinBlockID, MeinItemID;
}
Jetzt geht wieder zurück zu mod_MeinMod. Bisher müsste es so aussehen:
Ändert nun die 200 in PropsHelperMeinMod.MeinBlockID um und fügt dahinter noch eine ,0 ein! Nun fragt er jedesmal die ID des Blockes/Items in eurer Konfigurations Datei ab!
Wenn unklarheiten sind einfach im Thread fragen .
So sollte es aber schlussendlich aussehen:
5. RedStone Funktionen Porten
Nun Porten wir eine einfache Licht an/aus funktion!
In der mod_MeinMod:
Code:
LightOn1 = new BlockMeinLicht(PropsHelperMeinMod.LightOnID, 0, true).setHardness(0.6F).setBlockName("Light(ON)");
LightOff1 = new BlockMeinLicht(PropsHelperMeinMod.LightOffID, 0, false).setHardness(0.6F).setBlockName("Light");
Nun in Bukkit:
Code:
LightOn1 = new BlockMeinLicht(PropsHelperMeinMod.LightOnID, 0, true).c(0.6F).a("Light(ON)");
LightOff1 = new BlockMeinLicht(PropsHelperMeinMod.LightOffID, 0, false).c(0.6F).a("Light");
In der BlockMeinLicht:
Code:
package net.minecraft.src;
import net.minecraft.src.forge.*;
public class BlockMeinLicht extends Block implements ITextureProvider
{
private final boolean powered;
public BlockMeinLicht (int i, int j, boolean par2)
{
super(i, j, Material.cloth);
setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.065F, 1.0F);
this.powered = par2;
if (par2)
{
this.setLightValue(1.0F);
++this.blockIndexInTexture;
}
}
public boolean isOpaqueCube()
{
return false;
}
public boolean renderAsNormalBlock()
{
return false;
}
public void onBlockAdded(World par1World, int par2, int par3, int par4)
{
if (!par1World.isRemote)
{
if (this.powered && !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4))
{
par1World.setBlockWithNotify(par2, par3, par4, mod_MeinMod.LightOff1.blockID);
}
else if (!this.powered && par1World.isBlockIndirectlyGettingPowered(par2, par3, par4))
{
par1World.setBlockWithNotify(par2, par3, par4, mod_MeinMod.LightOn1.blockID);
}
}
}
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
{
if (!par1World.isRemote)
{
if (this.powered && !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4))
{
par1World.setBlockWithNotify(par2, par3, par4, mod_MeinMod.LightOf1.blockID);
}
else if (!this.powered && par1World.isBlockIndirectlyGettingPowered(par2, par3, par4))
{
par1World.setBlockWithNotify(par2, par3, par4, mod_MeinMod.LightOn1.blockID);
}
}
}
public String getTextureFile()
{
return "/Light/light.png";
}
}
Nun in Bukkit:
Code:
package net.minecraft.server;
import java.util.Random;
import forge.ITextureProvider;
public class BlockMeinLicht extends Block implements ITextureProvider
{
private final boolean powered;
public BlockMeinLicht(int i, int j, boolean par2)
{
super(i, j, Material.CLOTH);
a(0.0F, 0.0F, 0.0F, 1.0F, 0.065F, 1.0F);
this.powered = par2;
if (par2)
{
this.a(1.0F);
++this.textureId;
}
}
public boolean isOpaqueCube()
{
return false;
}
public boolean renderAsNormalBlock()
{
return false;
}
public int a(Random paramRandom) {
return 1;
}
public int getDropType(int paramInt1, Random paramRandom, int paramInt2) {
return mod_Rugs.RugsLightOff1.id;
}
public void onPlace(World par1World, int par2, int par3, int par4)
{
if (!par1World.isStatic)
{
if (this.powered && !par1World.isBlockIndirectlyPowered(par2, par3, par4))
{
par1World.setTypeId(par2, par3, par4, mod_MeinMod.LightOff1.id);
}
else if (!this.powered && par1World.isBlockIndirectlyPowered(par2, par3, par4))
{
par1World.setTypeId(par2, par3, par4, mod_MeinMod.LightOn1.id);
}
}
}public void doPhysics(World par1World, int par2, int par3, int par4, int par5)
{
if (!par1World.isStatic)
{
if (this.powered && !par1World.isBlockIndirectlyPowered(par2, par3, par4))
{
par1World.setTypeId(par2, par3, par4, mod_MeinMod.LightOff1.id);
}
else if (!this.powered && par1World.isBlockIndirectlyPowered(par2, par3, par4))
{
par1World.setTypeId(par2, par3, par4, mod_MeinMod.LightOn1.id);
}
}
}
public String getTextureFile()
{
return "/Light/light.png";
}
}
Vergleicht beide Codes sorgsam und ihr werdet wissen was zutun ist. Bei Unklarheiten könnt ihr mich natürlich fragen . 6. Porten mit Meta Daten
Als beispiel nehmen wir wieder unseren BlockMeinBlock. Erstellt zuerst eine neue Klasse z.b ItemMeinBlock fügt in diese folgenden Code hinzu:
Code:
package net.minecraft.server;
public class ItemMeinBlock extends ItemBlock
{
public ItemMeinBlock(int i)
{
super(i);
setMaxDurability(0);
a(true);
}
public int filterData(int metadata)
{
return metadata;
}
public static final String blockType[] =
{
"Yellow", "Orange", "Red", "Magenta", "Pink", "Purble", "Cyan", "LightBlue", "Blue", "Green", "Lime", "Brown", "LightGray", "Gray", "Black", "White" //Die einzelnen Namen der Blöcke
};
public String a(ItemStack itemstack)
{
return new StringBuilder().append("meinmod").append(blockType[itemstack.getData()]).toString(); //("meinmod") wird später bei den Namen gebraucht)
}
}
Öffnet eure BlockMeinBlock.java und fügt folgende Codes hinzu:
Code:
@Override
protected int getDropData(int metadata)
{
return metadata; //sagt das er den Block den du abbaust auch wiedergibt!
}
public int a(int side, int metadata)
{
if (metadata == 0 || metadata == 1)
{
return this.textureId + metadata; //hier könnte man auch stattdessen den Block mehre Texturen auf verschiedenen Seiten geben
}
return this.textureId + metadata;
}
Gut damit haben wir es fasst geschafft. Jetzt brauchen wir nur noch eine Erweiterung bei RegisterBlock. Also öffne deine mod_MeinMod und füge folgendes hinzu:
Bitte nehmt die Tutorials mehr als Wissensdatenbank wahr, den mit diesen Beispielen ist es einem Anfänger unmöglich eine Mod zu Porten, was auch so beabsichtigt ist. Wer Ahnung von Java und Mc Modding hat wird sich auch ohne meine Hilfe zurechtfinden!
Ich wünsche mir auf diesem Wege das es bekannter wird das es auch Mods für Bukkit gibt und das nicht grad wenige (Hier kuck) und nicht nur Plugins .
Hoffentlich konnte ich euch mit diesem Tutorial bzw. Wissensdatenbank, etwas weiterhelfen. Für Vorschläge, Kritik in angemessener Form bin ich immer offen!
Klasse Tutorial
Nur noch paar Fragen. Also 1. kann man einfach die neueste craftbukkit holen ?
2. man muss ja den text(sourcecode) ausm mod holen und da einfügen wo du gesagt hast. Aber was ist wenn bei einem Mod noch was zusätzlich dabei ist ? Also zum bsp "mod_blume" und dabei "BlockBlume" ?
1. Im Prinzip ja! Aber dann kannst du nur ohne Modloader etc. Programmieren, da in einem normalen Bukkit kein Modloader/Mp integriert ist! Ich empfehle dir immer von mcportcentral.co.za ein aktuelles Bukkit Build zu nehmen, da ist alles dabei und die Jungs sind auch ziemlich fix
2. Alle Dateien die der Mod besitzt müssen auch eingefügt werden und auch nur diese z.b. BlockDirt gehört NICHT in dein Projekt. mod_Blume z.b ist ein Modloader Mod und BlockBlume gehört mit dazu. Du musst halt bloss die Dateien an Bukkit anpassen!
mfg und Gute nacht
Geändert von neocromicon (04.04.2012 um 23:33 Uhr)
Man kann sie in die craftbukkit.jar einfügen, aber ich bevorzuge es die Mod direkt als .zip Archiv in den DeinServer/mods Ordner einzufügen. Lässt sich dann viel leichter Updaten .
Bisher ging das eigentlich mit jeder Mod ausser ein paar ausnahmen z.b. NotEnoughItems!
Und achte darauf deine Mod so zu verpacken das als erstes der net Ordner im Archiv/Craftbukkit.jar ist. Nicht wie gewohnt die Dateien als erstes .
182 recipes
27 achievements
java.lang.UnsatisfiedLinkError: C:\Users\akempf\AppData\Local\Temp\jline_git-Buk
kit-jenkins-CraftBukkit-63.dll: Can't load IA 32-bit .dll on a AMD 64-bit platfo
rm
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at jline.WindowsTerminal.loadLibrary(WindowsTerminal.java:315)
at jline.WindowsTerminal.initializeTerminal(WindowsTerminal.java:240)
at jline.Terminal.setupTerminal(Terminal.java:75)
at jline.Terminal.getTerminal(Terminal.java:26)
at jline.ConsoleReader.<init>(ConsoleReader.java:191)
at jline.ConsoleReader.<init>(ConsoleReader.java:186)
at net.minecraft.server.MinecraftServer.<init>(MinecraftServer.java:95)
at net.minecraft.server.MinecraftServer.main(MinecraftServer.java:614)
at org.bukkit.craftbukkit.Main.main(Main.java:134)
Press any key to continue . . .
Edit: (13.04.2012 um 13:18)
ich versteh den fehler net
5 Minuten Zeit? 5 Minuten Zeit. Ich liebe Zeit. Vor allem in Zeiten, in denen sie so knapp verlegt ist ...
182 recipes
27 achievements
java.lang.UnsatisfiedLinkError: C:\Users\akempf\AppData\Local\Temp\jline_git-Buk
kit-jenkins-CraftBukkit-63.dll: Can't load IA 32-bit .dll on a AMD 64-bit platfo
rm
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at jline.WindowsTerminal.loadLibrary(WindowsTerminal.java:315)
at jline.WindowsTerminal.initializeTerminal(WindowsTerminal.java:240)
at jline.Terminal.setupTerminal(Terminal.java:75)
at jline.Terminal.getTerminal(Terminal.java:26)
at jline.ConsoleReader.<init>(ConsoleReader.java:191)
at jline.ConsoleReader.<init>(ConsoleReader.java:186)
at net.minecraft.server.MinecraftServer.<init>(MinecraftServer.java:95)
at net.minecraft.server.MinecraftServer.main(MinecraftServer.java:614)
at org.bukkit.craftbukkit.Main.main(Main.java:134)
Press any key to continue . . .
Edit: (13.04.2012 um 13:18)
ich versteh den fehler net
Du versuchst eine 32Bit DLL für die IA Architektur (Intel) auf einem AMD 64 zu laden.
Das funktioniert nicht.. Das heißt du brauchst entweder eine native 32 bit DLL (für alle architekturen) oder explizit eine AMD64 DLL