[Server v5.8.0] German-MineClone2-server ( german )
Re: [Server] [v5.1.0] German-MineClone2-server
"Stein ist eines der wichtigsten Materialien"
"PVP ist hier zwar an, aber nicht erwünscht"
"Griefen ist nicht erlaubt"
"Am Spawn gibt es ein Regelbuch, in dem Alle Regeln stehen"
"Ein Diamant hat den Wert von 9 Münzen"
"Ein Eisenbarren hat den Wert von 1 Münze"
"Wenn ihr fly haben wollt, fragt erst gar nicht"
"Man KANN einen Kürbis auf den Kopf setzen, muss aber nicht, denn bei Lidl gibt's heute die 500g Packung für nur 99cent"
"Die Welt wird jeweils Montags und Freitags gesichert"
"Es wird nie Nacht"
"Man kann zwar in Betten nicht schlafen, aber sie setzen deinen Spawnpunkt"
"PVP ist hier zwar an, aber nicht erwünscht"
"Griefen ist nicht erlaubt"
"Am Spawn gibt es ein Regelbuch, in dem Alle Regeln stehen"
"Ein Diamant hat den Wert von 9 Münzen"
"Ein Eisenbarren hat den Wert von 1 Münze"
"Wenn ihr fly haben wollt, fragt erst gar nicht"
"Man KANN einen Kürbis auf den Kopf setzen, muss aber nicht, denn bei Lidl gibt's heute die 500g Packung für nur 99cent"
"Die Welt wird jeweils Montags und Freitags gesichert"
"Es wird nie Nacht"
"Man kann zwar in Betten nicht schlafen, aber sie setzen deinen Spawnpunkt"
Re: [Server] [v5.1.0] German-MineClone2-server
"Es gibt zwei Städte. Konya nördlich vom Spawn und Angle Town westlich vom Spawn"
"Die Melone ist das effizienteste Nahrungsmittel"
"Es gibt derzeit X Moderatoren: a,b und c"
"Dieses Spiel ist Minecraft orientiert. Das Minecraft Wiki hilft euch oft weiter"
"Am Spawn gibt es ein Zoo, aber leider keine Tiere^^"
"Häuser, die nur aus Erde bestehen werden gelöscht"
"Protecte dein Haus, damit es keiner griefen kann"
"Stein ist eines der wichtigsten Materialien"
"PVP ist hier zwar an, aber nicht erwünscht"
"Griefen ist nicht erlaubt"
"Am Spawn gibt es ein Regelbuch, in dem Alle Regeln stehen"
"Ein Diamant hat den Wert von 9 Münzen"
"Ein Eisenbarren hat den Wert von 1 Münze"
"Wenn ihr fly haben wollt, fragt erst gar nicht"
"Man KANN einen Kürbis auf den Kopf setzen, muss aber nicht, denn bei Lidl gibt's heute die 500g Packung für nur 99cent"
"Die Welt wird jeweils Montags und Freitags gesichert"
"Es wird nie Nacht"
"Man kann zwar in Betten nicht schlafen, aber sie setzen deinen Spawnpunkt"
Hier sind nochmal alle
"Die Melone ist das effizienteste Nahrungsmittel"
"Es gibt derzeit X Moderatoren: a,b und c"
"Dieses Spiel ist Minecraft orientiert. Das Minecraft Wiki hilft euch oft weiter"
"Am Spawn gibt es ein Zoo, aber leider keine Tiere^^"
"Häuser, die nur aus Erde bestehen werden gelöscht"
"Protecte dein Haus, damit es keiner griefen kann"
"Stein ist eines der wichtigsten Materialien"
"PVP ist hier zwar an, aber nicht erwünscht"
"Griefen ist nicht erlaubt"
"Am Spawn gibt es ein Regelbuch, in dem Alle Regeln stehen"
"Ein Diamant hat den Wert von 9 Münzen"
"Ein Eisenbarren hat den Wert von 1 Münze"
"Wenn ihr fly haben wollt, fragt erst gar nicht"
"Man KANN einen Kürbis auf den Kopf setzen, muss aber nicht, denn bei Lidl gibt's heute die 500g Packung für nur 99cent"
"Die Welt wird jeweils Montags und Freitags gesichert"
"Es wird nie Nacht"
"Man kann zwar in Betten nicht schlafen, aber sie setzen deinen Spawnpunkt"
Hier sind nochmal alle
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-10-28_04:29:58.tgz
Größe: 2.839.872.720 Bytes
Datum: 28.10.2019
Zeit: 04:29:58
File: Minetest_2019-10-28_04:29:58.tgz
Größe: 2.839.872.720 Bytes
Datum: 28.10.2019
Zeit: 04:29:58
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-01_06:01:55.tgz
Größe: 2.850.372.241 Bytes
Datum: 01.11.2019
Zeit: 06:01:55
File: Minetest_2019-11-01_06:01:55.tgz
Größe: 2.850.372.241 Bytes
Datum: 01.11.2019
Zeit: 06:01:55
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-04_03:52:03.tgz
Größe: 2.873.721.711 Bytes
Datum: 04.11.2019
Zeit: 03:52:03
File: Minetest_2019-11-04_03:52:03.tgz
Größe: 2.873.721.711 Bytes
Datum: 04.11.2019
Zeit: 03:52:03
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
WICHTIG: in den nächsten Tagen kann es bei ALLEN meiner Server zu längeren Downtimes kommen ( auch über Tage ), Grund sind Renovierungsarbeiten ( Schädlingsbekämpfung )
Es sollte nicht länger als eine Woche gehen.
Sobald es vorbei ist oder sich was ergibt, werde ich sofort hier bescheid geben.
Auch werde ich versuchen bei längeren Phasen hier nochmals explizit bescheid zu geben, kann dies jedoch nicht versprechen.
Kurz um: SERVER möglicherweisse mehrmahl über längere Zeit DOWN !!!
Geschätzte Dauer 5-7 Tage !!!
... Aktion auf unbestimmte Zeit verschoben
Es sollte nicht länger als eine Woche gehen.
Sobald es vorbei ist oder sich was ergibt, werde ich sofort hier bescheid geben.
Auch werde ich versuchen bei längeren Phasen hier nochmals explizit bescheid zu geben, kann dies jedoch nicht versprechen.
Kurz um: SERVER möglicherweisse mehrmahl über längere Zeit DOWN !!!
Geschätzte Dauer 5-7 Tage !!!
... Aktion auf unbestimmte Zeit verschoben
Last edited by Walker on Sat Nov 09, 2019 10:07, edited 1 time in total.
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-08_06:10:43.tgz
Größe: 2.822.905.391 Bytes
Datum: 08.11.2019
Zeit: 06:10:43
File: Minetest_2019-11-08_06:10:43.tgz
Größe: 2.822.905.391 Bytes
Datum: 08.11.2019
Zeit: 06:10:43
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Eine Algemeine Information:
Ich habe alle bei mir gehosteten Server nun in drei Blöcke aufgeteilt:
Server die VON MIR und FÜR MIR gehostet werden laufen unter den Portnummern 30000-30007 und werden, wie gehabt jeden Montag und Freitag Morgen gesichert ... das währen Folgende:
Server die VON MIR aber FÜR ANDERE gehostet werden laufen unter den Portnummern 30008-30015 und werden gesondert betreut ( Betriebsgeheimnis, da Verschwiegenheitspflicht besteht ) ... das währen den dann Folgende:
und dann gibt es noch eine Gruppe von VON MIR für TESTZWECKE ( aka Spielereien ) gehostete Server ... das sind alle von 30016-30031 ... und damit derzeit Folgende:
Ich habe alle bei mir gehosteten Server nun in drei Blöcke aufgeteilt:
Server die VON MIR und FÜR MIR gehostet werden laufen unter den Portnummern 30000-30007 und werden, wie gehabt jeden Montag und Freitag Morgen gesichert ... das währen Folgende:
Code: Select all
30000: German-Carpathian-server
30001: German-Ethereal-server
30002: German-Vanilla-server
30003: German-Creative-server
30004: German-MineClone2-server
Code: Select all
30008: Deutscher-Halloween-Server ( für HarryMonrow )
30014: Momos-Haus-Traum ( für Momo )
30015: bartonewelt ( privat, Passwortschutz )
Code: Select all
null
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-11_04:01:37.tgz
Größe: 2.855.780.896 Bytes
Datum: 11.11.2019
Zeit: 04:01:37
File: Minetest_2019-11-11_04:01:37.tgz
Größe: 2.855.780.896 Bytes
Datum: 11.11.2019
Zeit: 04:01:37
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-15_06:00:53.tgz
Größe: 2.879.315.083 Bytes
Datum: 15.11.2019
Zeit: 06:00:53
File: Minetest_2019-11-15_06:00:53.tgz
Größe: 2.879.315.083 Bytes
Datum: 15.11.2019
Zeit: 06:00:53
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
- Testperson
- New member
- Posts: 8
- Joined: Sun Nov 17, 2019 16:05
- GitHub: testperson-offiziell
- In-game: Testperson
Re: [Server] German-MineClone2-server
Soweit ich weiß gibt es doch einen Befehl, um den Text wer Administrator ist zu ändern. Klappt das nicht?Walker wrote:ja,leider greift die Terminal Funktion von Minetest IMMER auf den Admin zu, und da ich, wenn ich per Console unterwegs bin gerne dies erkendlich machen möchte, muss ich den Admin "Walker-Console" nennen, damit mein name in der Console ebend so heißt. Und ich bin, wenn ich als aktiver Spieler mitspiele, als "Walker" unterwegs, und damit mit einem Normal Accound, der aber alle Rechte hat ...
jodoch wird auf diese gegebenheit per MOTD hingewiessen ;)
by Testperson
Discord: https://discord.gg/B2eTZ4
Ingame: Testperson ; Github: testperson-offiziell ; YouTube: TESTPERSON
Discord: https://discord.gg/B2eTZ4
Ingame: Testperson ; Github: testperson-offiziell ; YouTube: TESTPERSON
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-18_04:00:10.tgz
Größe: 2.930.818.674 Bytes
Datum: 18.11.2019
Zeit: 04:00:10
File: Minetest_2019-11-18_04:00:10.tgz
Größe: 2.930.818.674 Bytes
Datum: 18.11.2019
Zeit: 04:00:10
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] German-MineClone2-server
und welcher Befehl währe das !?Testperson wrote:Soweit ich weiß gibt es doch einen Befehl, um den Text wer Administrator ist zu ändern. Klappt das nicht?Walker wrote:ja,leider greift die Terminal Funktion von Minetest IMMER auf den Admin zu, und da ich, wenn ich per Console unterwegs bin gerne dies erkendlich machen möchte, muss ich den Admin "Walker-Console" nennen, damit mein name in der Console ebend so heißt. Und ich bin, wenn ich als aktiver Spieler mitspiele, als "Walker" unterwegs, und damit mit einem Normal Accound, der aber alle Rechte hat ...
jodoch wird auf diese gegebenheit per MOTD hingewiessen ;)
Ich dachte sowas muss in die minetest.conf !?!
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Kurzinfo: quick-fix v0.55.1 eingespielt ...
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.0.0] German-MineClone2-server
ist der Code zu 0.55.1 kompatibel ?jjk1 wrote:So jetzt hab ich's. Dieser Code funktioniert jetzt wirklich zu 100%:Code: Select all
--MCmobs v0.4 --maikerumine --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes --################### --################### VILLAGER --################### -- Summary: Villagers are complex NPCs, their main feature allows players to trade with them. -- TODO: Particles -- TODO: 4s Regeneration I after trade unlock -- TODO: Breeding -- TODO: Baby villagers -- TODO: Spawning in villages -- TODO: Behaviour: -- TODO: Walk around village, but do not leave it intentionally -- TODO: Run into house on rain or danger, open doors -- TODO: Internal inventory, pick up items, trade with other villagers -- TODO: Farm stuff local S = minetest.get_translator("mobs_mc") local N = function(s) return s end -- playername-indexed table containing the previously used tradenum local player_tradenum = {} -- playername-indexed table containing the objectref of trader, if trading formspec is open local player_trading_with = {} local DEFAULT_WALK_CHANCE = 10 -- chance to walk in percent, if no player nearby local PLAYER_SCAN_INTERVAL = 5 -- every X seconds, villager looks for players nearby local PLAYER_SCAN_RADIUS = 4 -- scan radius for looking for nearby players --[=======[ TRADING ]=======] -- LIST OF VILLAGER PROFESSIONS AND TRADES -- TECHNICAL RESTRICTIONS (FIXME): -- * You can't use a clock as requested item -- * You can't use a compass as requested item if its stack size > 1 -- * You can't use a compass in the second requested slot -- This is a problem in the mcl_compass and mcl_clock mods, -- these items should be implemented as single items, then everything -- will be much easier. local COMPASS = "mcl_compass:compass" if minetest.registered_aliases[COMPASS] then COMPASS = minetest.registered_aliases[COMPASS] end local E1 = { "mcl_shops:coin", 1, 1 } -- one emerald local professions = { farmer = { name = N("Farmer"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_farming:wheat_item", 18, 22, }, {"mcl_shops:coin", 1, 1} }, { { "mcl_farming:potato_item", 15, 19, }, {"mcl_shops:coin", 1, 1} }, { { "mcl_farming:carrot_item", 15, 19, }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_farming:bread", 2, 4 } }, }, { { { "mcl_farming:pumpkin_face", 8, 12 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_farming:pumpkin_pie", 2, 3} }, }, { { { "mcl_farming:melon_item", 7, 12 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_core:apple", 5, 7 }, }, }, { { {"mcl_shops:coin", 1, 1}, { "mcl_farming:cookie", 6, 10 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_cake:cake", 1, 1 } } }, } }, fisherman = { name = N("Fisherman"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_fishing:fish_raw", 6, 6, "mcl_shops:coin", 1, 1 }, { "mcl_fishing:fish_cooked", 6, 6 } }, { { "mcl_mobitems:string", 5, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_core:coal_lump", 5, 7 }, {"mcl_shops:coin", 1, 1} }, }, -- TODO: enchanted fishing rod }, }, fletcher = { name = N("Fletcher"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_mobitems:string", 5, 7 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_bows:arrow", 8, 12 } }, }, { { { "mcl_core:gravel", 10, 10, "mcl_shops:coin", 1, 1 }, { "mcl_core:flint", 6, 10 } }, { { "mcl_shops:coin", 2, 3 }, { "mcl_bows:bow", 1, 1 } }, }, } }, shepherd ={ name = N("Shepherd"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_wool:white", 3, 5 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 3, 4 }, { "mcl_tools:shears", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:white", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:grey", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:silver", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:black", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:yellow", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:orange", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:red", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:magenta", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:purple", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:blue", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:cyan", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:lime", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:green", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:pink", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:light_blue", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:brown", 3, 5 } }, }, }, }, librarian = { name = N("Librarian"), texture = "mobs_mc_villager_librarian.png", trades = { { { { "mcl_core:paper", 24, 36 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchanted book { { "mcl_books:book", 8, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 4, 5 }, { "mcl_compass:compass", 1 ,1 }}, { { "mcl_shops:coin", 3, 4 }, { "mcl_books:bookshelf", 1 ,1 }}, }, { { { "mcl_books:written_book", 2, 2 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 9, 11 }, { "mcl_clock:clock", 1, 1 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_core:glass", 5, 7 } }, }, { { {"mcl_shops:coin", 1, 1}, { "mcl_core:glass", 5, 7 } }, }, -- TODO: 2 enchanted book tiers { { { "mcl_shops:coin", 20, 22 }, { "mcl_mobs:nametag", 1, 1 } }, } }, }, cartographer = { name = N("Cartographer"), texture = "mobs_mc_villager_librarian.png", trades = { { { { "mcl_core:paper", 20, 30 }, {"mcl_shops:coin", 1, 1} }, }, { -- subject to special checks { { "mcl_compass:compass", 1, 1 }, {"mcl_shops:coin", 4, 5} }, }, { -- TODO: replace with empty map { { "mcl_shops:coin", 5, 10}, { "mcl_maps:filled_map", 1, 1 } }, }, -- TODO: special maps }, }, armorer = { name = N("Armorer"), texture = "mobs_mc_villager_smith.png", trades = { { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 4, 6 }, { "3d_armor:helmet_iron", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 1 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 7, 9 }, { "3d_armor:chestplate_iron", 1, 1 } }, }, { { { "mcl_core:diamond", 1, 1 }, {"mcl_shops:coin", 9, 9} }, -- TODO: enchant { { "mcl_shops:coin", 26, 28 }, { "3d_armor:chestplate_gold", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 2 }, { "3d_armor:boots_chain", 1, 1 } }, { { "mcl_shops:coin", 2, 3 }, { "3d_armor:leggings_chain", 1, 1 } }, { { "mcl_shops:coin", 1, 2 }, { "3d_armor:helmet_chain", 1, 1 } }, { { "mcl_shops:coin", 3, 4 }, { "3d_armor:chestplate_chain", 1, 1 } }, }, }, }, leatherworker = { name = N("Leatherworker"), texture = "mobs_mc_villager_butcher.png", trades = { { { { "mcl_mobitems:leather", 5, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 3, 5 }, { "3d_armor:leggings_leather", 2, 4 } }, }, { -- TODO: enchant { { "mcl_shops:coin", 4, 7 }, { "3d_armor:chestplate_leather", 1, 1 } }, }, { { { "mcl_shops:coin", 15, 20 }, { "mcl_mobitems:saddle", 1, 1 } }, }, }, }, butcher = { name = N("Butcher"), texture = "mobs_mc_villager_butcher.png", trades = { { { { "mcl_mobitems:beef", 5, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_mobitems:chicken", 5, 10 }, {"mcl_shops:coin", 1, 1} }, }, { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_mobitems:cooked_beef", 5, 10 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_mobitems:cooked_chicken", 5, 10 } }, }, }, }, weapon_smith = { name = N("Weapon Smith"), texture = "mobs_mc_villager_smith.png", trades = { { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 3, 4 }, { "mcl_tools:axe_iron", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 1 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchant { { "mcl_shops:coin", 2, 3 }, { "mcl_tools:sword_iron", 1, 1 } }, }, { { { "mcl_core:diamond", 1, 1 }, {"mcl_shops:coin", 9, 9 } }, -- TODO: enchant { { "mcl_shops:coin", 17, 19 }, { "mcl_tools:sword_diamond", 1, 1 } }, -- TODO: enchant { { "mcl_shops:coin", 27, 28 }, { "mcl_tools:axe_diamond", 1, 1 } }, }, }, }, tool_smith = { name = N("Tool Smith"), texture = "mobs_mc_villager_smith.png", trades = { { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchant { { "mcl_shops:coin", 1, 1 }, { "mcl_tools:shovel_iron", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 1 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchant { { "mcl_shops:coin", 2, 4 }, { "mcl_tools:pick_iron", 1, 1 } }, }, { { { "mcl_core:diamond", 1, 1 }, {"mcl_shops:coin", 9, 9 } }, -- TODO: enchant { { "mcl_shops:coin", 26, 28 }, { "mcl_tools:pick_diamond", 1, 1 } }, }, }, }, cleric = { name = N("Cleric"), texture = "mobs_mc_villager_priest.png", trades = { { { { "mcl_mobitems:rotten_flesh", 15, 25 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_core:gold_ingot", 2, 2 }, {"mcl_shops:coin", 6, 6 } }, }, { { {"mcl_shops:coin", 1, 1}, { "mesecons:redstone", 1, 4 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_dye:blue", 1, 2 } }, }, { { {"mcl_shops:coin", 1, 1}, { "mcl_nether:glowstone", 1, 3 } }, { { "mcl_shops:coin", 4, 7 }, { "mcl_throwing:ender_pearl", 1, 1 } }, TRADE_V6_RED_SANDSTONE, }, -- TODO: Bottle 'o enchanting }, }, nitwit = { name = N("Nitwit"), texture = "mobs_mc_villager.png", -- No trades for nitwit trades = nil, } } local profession_names = {} for id, _ in pairs(professions) do table.insert(profession_names, id) end local stand_still = function(self) self.walk_chance = 0 self.jump = false end local update_max_tradenum = function(self) if not self._trades then return end local trades = minetest.deserialize(self._trades) for t=1, #trades do local trade = trades[t] if trade.tier > self._max_trade_tier then self._max_tradenum = t - 1 return end end self._max_tradenum = #trades end local init_trader_vars = function(self) if not self._profession then -- Select random profession from all professions with matching clothing local texture = self.base_texture[1] local matches = {} for prof_id, prof in pairs(professions) do if texture == prof.texture then table.insert(matches, prof_id) end end local p = math.random(1, #matches) self._profession = matches[p] end if not self._max_trade_tier then self._max_trade_tier = 1 end if not self._locked_trades then self._locked_trades = 0 end if not self._trading_players then self._trading_players = {} end end local init_trades = function(self, inv) local profession = professions[self._profession] local trade_tiers = profession.trades if trade_tiers == nil then -- Empty trades self._trades = false return end local max_tier = #trade_tiers local trades = {} for tiernum=1, max_tier do local tier = trade_tiers[tiernum] for tradenum=1, #tier do local trade = tier[tradenum] local wanted1_item = trade[1][1] local wanted1_count = math.random(trade[1][2], trade[1][3]) local offered_item = trade[2][1] local offered_count = math.random(trade[2][2], trade[2][3]) local wanted = { wanted1_item .. " " ..wanted1_count } if trade[1][4] then local wanted2_item = trade[1][4] local wanted2_count = math.random(trade[1][5], trade[1][6]) table.insert(wanted, wanted2_item .. " " ..wanted2_count) end table.insert(trades, { wanted = wanted, offered = offered_item .. " " .. offered_count, tier = tiernum, -- tier of this trade traded_once = false, -- true if trade was traded at least once trade_counter = 0, -- how often the this trade was mate after the last time it got unlocked locked = false, -- if this trade is locked. Locked trades can't be used }) end end self._trades = minetest.serialize(trades) end local set_trade = function(trader, player, inv, concrete_tradenum) local trades = minetest.deserialize(trader._trades) if not trades then init_trades(trader) trades = minetest.deserialize(trader._trades) if not trades then minetest.log("error", "[mobs_mc] Failed to select villager trade!") return end end local name = player:get_player_name() -- Stop tradenum from advancing into locked tiers or out-of-range areas if concrete_tradenum > trader._max_tradenum then concrete_tradenum = trader._max_tradenum elseif concrete_tradenum < 1 then concrete_tradenum = 1 end player_tradenum[name] = concrete_tradenum local trade = trades[concrete_tradenum] inv:set_stack("wanted", 1, ItemStack(trade.wanted[1])) inv:set_stack("offered", 1, ItemStack(trade.offered)) if trade.wanted[2] then local wanted2 = ItemStack(trade.wanted[2]) inv:set_stack("wanted", 2, wanted2) else inv:set_stack("wanted", 2, "") end end local function show_trade_formspec(playername, trader, tradenum) if not trader._trades then return end if not tradenum then tradenum = 1 end local trades = minetest.deserialize(trader._trades) local trade = trades[tradenum] local profession = professions[trader._profession].name local disabled_img = "" if trade.locked then disabled_img = "image[4.3,2.52;1,1;mobs_mc_trading_formspec_disabled.png]".. "image[4.3,1.1;1,1;mobs_mc_trading_formspec_disabled.png]" end local tradeinv_name = "mobs_mc:trade_"..playername local tradeinv = minetest.formspec_escape("detached:"..tradeinv_name) local b_prev, b_next = "", "" if #trades > 1 then if tradenum > 1 then b_prev = "button[1,1;0.5,1;prev_trade;<]" end if tradenum < trader._max_tradenum then b_next = "button[7.26,1;0.5,1;next_trade;>]" end end local formspec = "size[9,8.75]" .."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]" ..disabled_img ..mcl_vars.inventory_header .."label[4,0;"..minetest.formspec_escape(minetest.colorize("#313131", S(profession))).."]" .."list[current_player;main;0,4.5;9,3;9]" .."list[current_player;main;0,7.74;9,1;]" ..b_prev..b_next .."list["..tradeinv..";wanted;2,1;2,1;]" .."list["..tradeinv..";offered;5.76,1;1,1;]" .."list["..tradeinv..";input;2,2.5;2,1;]" .."list["..tradeinv..";output;5.76,2.55;1,1;]" .."listring["..tradeinv..";output]" .."listring[current_player;main]" .."listring["..tradeinv..";input]" .."listring[current_player;main]" minetest.sound_play("mobs_mc_villager_trade", {to_player = playername}) minetest.show_formspec(playername, tradeinv_name, formspec) end local update_offer = function(inv, player, sound) local name = player:get_player_name() local trader = player_trading_with[name] local tradenum = player_tradenum[name] if not trader or not tradenum then return false end local trades = minetest.deserialize(trader._trades) if not trades then return false end local trade = trades[tradenum] if not trade then return false end local wanted1, wanted2 = inv:get_stack("wanted", 1), inv:get_stack("wanted", 2) local input1, input2 = inv:get_stack("input", 1), inv:get_stack("input", 2) -- BEGIN OF SPECIAL HANDLING OF COMPASS -- These 2 functions are a complicated check to check if the input contains a -- special item which we cannot check directly against their name, like -- compass. -- TODO: Remove these check functions when compass and clock are implemented -- as single items. local check_special = function(special_item, group, wanted1, wanted2, input1, input2) if minetest.registered_aliases[special_item] then special_item = minetest.registered_aliases[special_item] end if wanted1:get_name() == special_item then local check_input = function(input, wanted, group) return minetest.get_item_group(input:get_name(), group) ~= 0 and input:get_count() >= wanted:get_count() end if check_input(input1, wanted1, group) then return true elseif check_input(input2, wanted1, group) then return true else return false end end return false end -- Apply above function to all items which we consider special. -- This function succeeds if ANY item check succeeds. local check_specials = function(wanted1, wanted2, input1, input2) return check_special(COMPASS, "compass", wanted1, wanted2, input1, input2) end -- END OF SPECIAL HANDLING OF COMPASS if ( ((inv:contains_item("input", wanted1) and (wanted2:is_empty() or inv:contains_item("input", wanted2))) or -- BEGIN OF SPECIAL HANDLING OF COMPASS check_specials(wanted1, wanted2, input1, input2)) and -- END OF SPECIAL HANDLING OF COMPASS (trade.locked == false)) then inv:set_stack("output", 1, inv:get_stack("offered", 1)) if sound then minetest.sound_play("mobs_mc_villager_accept", {to_player = name}) end return true else inv:set_stack("output", 1, ItemStack("")) if sound then minetest.sound_play("mobs_mc_villager_deny", {to_player = name}) end return false end end -- Returns a single itemstack in the given inventory to the player's main inventory, or drop it when there's no space left local function return_item(itemstack, dropper, pos, inv_p) if dropper:is_player() then -- Return to main inventory if inv_p:room_for_item("main", itemstack) then inv_p:add_item("main", itemstack) else -- Drop item on the ground local v = dropper:get_look_dir() local p = {x=pos.x, y=pos.y+1.2, z=pos.z} p.x = p.x+(math.random(1,3)*0.2) p.z = p.z+(math.random(1,3)*0.2) local obj = minetest.add_item(p, itemstack) if obj then v.x = v.x*4 v.y = v.y*4 + 2 v.z = v.z*4 obj:set_velocity(v) obj:get_luaentity()._insta_collect = false end end else -- Fallback for unexpected cases minetest.add_item(pos, itemstack) end return itemstack end local return_fields = function(player) local name = player:get_player_name() local inv_t = minetest.get_inventory({type="detached", name = "mobs_mc:trade_"..name}) local inv_p = player:get_inventory() for i=1, inv_t:get_size("input") do local stack = inv_t:get_stack("input", i) return_item(stack, player, player:get_pos(), inv_p) stack:clear() inv_t:set_stack("input", i, stack) end inv_t:set_stack("output", 1, "") end minetest.register_on_player_receive_fields(function(player, formname, fields) if string.sub(formname, 1, 14) == "mobs_mc:trade_" then local name = player:get_player_name() if fields.quit then -- Get input items back return_fields(player) -- Reset internal "trading with" state local trader = player_trading_with[name] if trader then trader._trading_players[name] = nil end player_trading_with[name] = nil elseif fields.next_trade or fields.prev_trade then local trader = player_trading_with[name] if not trader or not trader.object:get_luaentity() then return end local trades = trader._trades if not trades then return end local dir = 1 if fields.prev_trade then dir = -1 end local tradenum = player_tradenum[name] + dir local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade_"..name}) set_trade(trader, player, inv, tradenum) update_offer(inv, player, false) show_trade_formspec(name, trader, player_tradenum[name]) end end end) minetest.register_on_leaveplayer(function(player) local name = player:get_player_name() return_fields(player) player_tradenum[name] = nil local trader = player_trading_with[name] if trader then trader._trading_players[name] = nil end player_trading_with[name] = nil end) -- Return true if player is trading with villager, and the villager entity exists local trader_exists = function(playername) local trader = player_trading_with[playername] return trader ~= nil and trader.object:get_luaentity() ~= nil end local trade_inventory = { allow_take = function(inv, listname, index, stack, player) if listname == "input" then return stack:get_count() elseif listname == "output" then if not trader_exists(player:get_player_name()) then return 0 end -- Only allow taking full stack local count = stack:get_count() if count == inv:get_stack(listname, index):get_count() then -- Also update output stack again. -- If input has double the wanted items, the -- output will stay because there will be still -- enough items in input after the trade local wanted1 = inv:get_stack("wanted", 1) local wanted2 = inv:get_stack("wanted", 2) local input1 = inv:get_stack("input", 1) local input2 = inv:get_stack("input", 2) wanted1:set_count(wanted1:get_count()*2) wanted2:set_count(wanted2:get_count()*2) -- BEGIN OF SPECIAL HANDLING FOR COMPASS local special_checks = function(wanted1, input1, input2) if wanted1:get_name() == COMPASS then local compasses = 0 if (minetest.get_item_group(input1:get_name(), "compass") ~= 0) then compasses = compasses + input1:get_count() end if (minetest.get_item_group(input2:get_name(), "compass") ~= 0) then compasses = compasses + input2:get_count() end return compasses >= wanted1:get_count() end return false end -- END OF SPECIAL HANDLING FOR COMPASS if (inv:contains_item("input", wanted1) and (wanted2:is_empty() or inv:contains_item("input", wanted2))) -- BEGIN OF SPECIAL HANDLING FOR COMPASS or special_checks(wanted1, input1, input2) then -- END OF SPECIAL HANDLING FOR COMPASS return -1 else -- If less than double the wanted items, -- remove items from output (final trade, -- input runs empty) return count end else return 0 end else return 0 end end, allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) if from_list == "input" and to_list == "input" then return count elseif from_list == "output" and to_list == "input" then if not trader_exists(player:get_player_name()) then return 0 end local move_stack = inv:get_stack(from_list, from_index) if inv:get_stack(to_list, to_index):item_fits(move_stack) then return count end end return 0 end, allow_put = function(inv, listname, index, stack, player) if listname == "input" then if not trader_exists(player:get_player_name()) then return 0 else return stack:get_count() end else return 0 end end, on_put = function(inv, listname, index, stack, player) update_offer(inv, player, true) end, on_move = function(inv, from_list, from_index, to_list, to_index, count, player) if from_list == "output" and to_list == "input" then inv:remove_item("input", inv:get_stack("wanted", 1)) local wanted2 = inv:get_stack("wanted", 2) if not wanted2:is_empty() then inv:remove_item("input", inv:get_stack("wanted", 2)) end minetest.sound_play("mobs_mc_villager_accept", {to_player = player:get_player_name()}) end update_offer(inv, player, true) end, on_take = function(inv, listname, index, stack, player) local accept local name = player:get_player_name() if listname == "output" then local wanted1 = inv:get_stack("wanted", 1) inv:remove_item("input", wanted1) local wanted2 = inv:get_stack("wanted", 2) if not wanted2:is_empty() then inv:remove_item("input", inv:get_stack("wanted", 2)) end -- BEGIN OF SPECIAL HANDLING FOR COMPASS if wanted1:get_name() == COMPASS then for n=1, 2 do local input = inv:get_stack("input", n) if minetest.get_item_group(input:get_name(), "compass") ~= 0 then input:set_count(input:get_count() - wanted1:get_count()) inv:set_stack("input", n, input) break end end end -- END OF SPECIAL HANDLING FOR COMPASS local trader = player_trading_with[name] local tradenum = player_tradenum[name] local trades if trader and trader._trades then trades = minetest.deserialize(trader._trades) end if trades then local trade = trades[tradenum] local unlock_stuff = false if not trade.traded_once then -- Unlock all the things if something was traded -- for the first time ever unlock_stuff = true trade.traded_once = true elseif trade.trade_counter == 0 and math.random(1,5) == 1 then -- Otherwise, 20% chance to unlock if used freshly reset trade unlock_stuff = true end local update_formspec = false if unlock_stuff then -- First-time trade unlock all trades and unlock next trade tier if trade.tier + 1 > trader._max_trade_tier then trader._max_trade_tier = trader._max_trade_tier + 1 update_max_tradenum(trader) update_formspec = true end for t=1, #trades do trades[t].locked = false trades[t].trade_counter = 0 end trader._locked_trades = 0 -- Also heal trader for unlocking stuff -- TODO: Replace by Regeneration I trader.health = math.min(trader.hp_max, trader.health + 4) end trade.trade_counter = trade.trade_counter + 1 -- Semi-randomly lock trade for repeated trade (not if there's only 1 trade) if trader._max_tradenum > 1 then if trade.trade_counter >= 12 then trade.locked = true elseif trade.trade_counter >= 2 then local r = math.random(1, math.random(4, 10)) if r == 1 then trade.locked = true end end end if trade.locked then inv:set_stack("output", 1, "") update_formspec = true trader._locked_trades = trader._locked_trades + 1 -- Check if we managed to lock ALL available trades. Rare but possible. if trader._locked_trades >= trader._max_tradenum then -- Emergency unlock! Unlock all other trades except the current one for t=1, #trades do if t ~= tradenum then trades[t].locked = false trades[t].trade_counter = 0 end end trader._locked_trades = 1 -- Also heal trader for unlocking stuff -- TODO: Replace by Regeneration I trader.health = math.min(trader.hp_max, trader.health + 4) end end trader._trades = minetest.serialize(trades) if update_formspec then show_trade_formspec(name, trader, tradenum) end else minetest.log("error", "[mobs_mc] Player took item from trader output but player_trading_with or player_tradenum is nil!") end accept = true elseif listname == "input" then update_offer(inv, player, false) end if accept then minetest.sound_play("mobs_mc_villager_accept", {to_player = name}) else minetest.sound_play("mobs_mc_villager_deny", {to_player = name}) end end, } minetest.register_on_joinplayer(function(player) local name = player:get_player_name() player_tradenum[name] = 1 player_trading_with[name] = nil -- Create or get player-specific trading inventory local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade_"..name}) if not inv then inv = minetest.create_detached_inventory("mobs_mc:trade_"..name, trade_inventory, name) end inv:set_size("input", 2) inv:set_size("output", 1) inv:set_size("wanted", 2) inv:set_size("offered", 1) end) --[=======[ MOB REGISTRATION AND SPAWNING ]=======] mobs:register_mob("mobs_mc:villager", { type = "npc", hp_min = 20, hp_max = 20, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_villager.b3d", textures = { { "mobs_mc_villager.png", "mobs_mc_villager.png", --hat }, { "mobs_mc_villager_farmer.png", "mobs_mc_villager_farmer.png", --hat }, { "mobs_mc_villager_priest.png", "mobs_mc_villager_priest.png", --hat }, { "mobs_mc_villager_librarian.png", "mobs_mc_villager_librarian.png", --hat }, { "mobs_mc_villager_butcher.png", "mobs_mc_villager_butcher.png", --hat }, { "mobs_mc_villager_smith.png", "mobs_mc_villager_smith.png", --hat }, }, visual_size = {x=3, y=3}, makes_footstep_sound = true, walk_velocity = 1.2, run_velocity = 2.4, drops = {}, -- TODO: sounds animation = { stand_speed = 25, stand_start = 40, stand_end = 59, walk_speed = 25, walk_start = 0, walk_end = 40, run_speed = 25, run_start = 0, run_end = 40, die_speed = 15, die_start = 210, die_end = 220, die_loop = false, }, water_damage = 0, lava_damage = 4, light_damage = 0, view_range = 16, fear_height = 4, jump = true, walk_chance = DEFAULT_WALK_CHANCE, on_rightclick = function(self, clicker) -- Initiate trading local name = clicker:get_player_name() self._trading_players[name] = true init_trader_vars(self) if self._trades == nil then init_trades(self) end update_max_tradenum(self) if self._trades == false then -- Villager has no trades, rightclick is a no-op return end player_trading_with[name] = self local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade_"..name}) set_trade(self, clicker, inv, 1) show_trade_formspec(name, self) -- Behaviour stuff: -- Make villager look at player and stand still local selfpos = self.object:get_pos() local clickerpos = clicker:get_pos() local dir = vector.direction(selfpos, clickerpos) self.object:set_yaw(minetest.dir_to_yaw(dir)) stand_still(self) end, _player_scan_timer = 0, _trading_players = {}, -- list of playernames currently trading with villager (open formspec) do_custom = function(self, dtime) -- Stand still if player is nearby. if not self._player_scan_timer then self._player_scan_timer = 0 end self._player_scan_timer = self._player_scan_timer + dtime -- Check infrequently to keep CPU load low if self._player_scan_timer > PLAYER_SCAN_INTERVAL then self._player_scan_timer = 0 local selfpos = self.object:get_pos() local objects = minetest.get_objects_inside_radius(selfpos, PLAYER_SCAN_RADIUS) local has_player = false for o, obj in pairs(objects) do if obj:is_player() then has_player = true break end end if has_player then minetest.log("verbose", "[mobs_mc] Player near villager found!") stand_still(self) else minetest.log("verbose", "[mobs_mc] No player near villager found!") self.walk_chance = DEFAULT_WALK_CHANCE self.jump = true end end end, on_spawn = function(self) init_trader_vars(self) end, on_die = function(self, pos) -- Close open trade formspecs and give input back to players local trading_players = self._trading_players for name, _ in pairs(trading_players) do minetest.close_formspec(name, "mobs_mc:trade_"..name) local player = minetest.get_player_by_name(name) if player then return_fields(player) end end end, }) mobs:spawn_specific("mobs_mc:villager", mobs_mc.spawn.village, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 8000, 4, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max) -- compatibility mobs:alias_mob("mobs:villager", "mobs_mc:villager") -- spawn eggs mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0) if minetest.settings:get_bool("log_mods") then minetest.log("action", "MC mobs loaded") end
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
theoretisch schon, es wurde ja nichts an den Dörfern geändert
Re: [Server] [v5.0.0] German-MineClone2-server
Patch wurde erneut eingespielt, danke nochmal für die Arbeit jjk1 ;)jjk1 wrote:So jetzt hab ich's. Dieser Code funktioniert jetzt wirklich zu 100%:Code: Select all
--MCmobs v0.4 --maikerumine --made for MC like Survival game --License for code WTFPL and otherwise stated in readmes --################### --################### VILLAGER --################### -- Summary: Villagers are complex NPCs, their main feature allows players to trade with them. -- TODO: Particles -- TODO: 4s Regeneration I after trade unlock -- TODO: Breeding -- TODO: Baby villagers -- TODO: Spawning in villages -- TODO: Behaviour: -- TODO: Walk around village, but do not leave it intentionally -- TODO: Run into house on rain or danger, open doors -- TODO: Internal inventory, pick up items, trade with other villagers -- TODO: Farm stuff local S = minetest.get_translator("mobs_mc") local N = function(s) return s end -- playername-indexed table containing the previously used tradenum local player_tradenum = {} -- playername-indexed table containing the objectref of trader, if trading formspec is open local player_trading_with = {} local DEFAULT_WALK_CHANCE = 10 -- chance to walk in percent, if no player nearby local PLAYER_SCAN_INTERVAL = 5 -- every X seconds, villager looks for players nearby local PLAYER_SCAN_RADIUS = 4 -- scan radius for looking for nearby players --[=======[ TRADING ]=======] -- LIST OF VILLAGER PROFESSIONS AND TRADES -- TECHNICAL RESTRICTIONS (FIXME): -- * You can't use a clock as requested item -- * You can't use a compass as requested item if its stack size > 1 -- * You can't use a compass in the second requested slot -- This is a problem in the mcl_compass and mcl_clock mods, -- these items should be implemented as single items, then everything -- will be much easier. local COMPASS = "mcl_compass:compass" if minetest.registered_aliases[COMPASS] then COMPASS = minetest.registered_aliases[COMPASS] end local E1 = { "mcl_shops:coin", 1, 1 } -- one emerald local professions = { farmer = { name = N("Farmer"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_farming:wheat_item", 18, 22, }, {"mcl_shops:coin", 1, 1} }, { { "mcl_farming:potato_item", 15, 19, }, {"mcl_shops:coin", 1, 1} }, { { "mcl_farming:carrot_item", 15, 19, }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_farming:bread", 2, 4 } }, }, { { { "mcl_farming:pumpkin_face", 8, 12 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_farming:pumpkin_pie", 2, 3} }, }, { { { "mcl_farming:melon_item", 7, 12 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_core:apple", 5, 7 }, }, }, { { {"mcl_shops:coin", 1, 1}, { "mcl_farming:cookie", 6, 10 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_cake:cake", 1, 1 } } }, } }, fisherman = { name = N("Fisherman"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_fishing:fish_raw", 6, 6, "mcl_shops:coin", 1, 1 }, { "mcl_fishing:fish_cooked", 6, 6 } }, { { "mcl_mobitems:string", 5, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_core:coal_lump", 5, 7 }, {"mcl_shops:coin", 1, 1} }, }, -- TODO: enchanted fishing rod }, }, fletcher = { name = N("Fletcher"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_mobitems:string", 5, 7 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_bows:arrow", 8, 12 } }, }, { { { "mcl_core:gravel", 10, 10, "mcl_shops:coin", 1, 1 }, { "mcl_core:flint", 6, 10 } }, { { "mcl_shops:coin", 2, 3 }, { "mcl_bows:bow", 1, 1 } }, }, } }, shepherd ={ name = N("Shepherd"), texture = "mobs_mc_villager_farmer.png", trades = { { { { "mcl_wool:white", 3, 5 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 3, 4 }, { "mcl_tools:shears", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:white", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:grey", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:silver", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:black", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:yellow", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:orange", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:red", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:magenta", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:purple", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:blue", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:cyan", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:lime", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:green", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:pink", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:light_blue", 3, 5 } }, { { "mcl_shops:coin", 1, 2 }, { "mcl_wool:brown", 3, 5 } }, }, }, }, librarian = { name = N("Librarian"), texture = "mobs_mc_villager_librarian.png", trades = { { { { "mcl_core:paper", 24, 36 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchanted book { { "mcl_books:book", 8, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 4, 5 }, { "mcl_compass:compass", 1 ,1 }}, { { "mcl_shops:coin", 3, 4 }, { "mcl_books:bookshelf", 1 ,1 }}, }, { { { "mcl_books:written_book", 2, 2 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 9, 11 }, { "mcl_clock:clock", 1, 1 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_core:glass", 5, 7 } }, }, { { {"mcl_shops:coin", 1, 1}, { "mcl_core:glass", 5, 7 } }, }, -- TODO: 2 enchanted book tiers { { { "mcl_shops:coin", 20, 22 }, { "mcl_mobs:nametag", 1, 1 } }, } }, }, cartographer = { name = N("Cartographer"), texture = "mobs_mc_villager_librarian.png", trades = { { { { "mcl_core:paper", 20, 30 }, {"mcl_shops:coin", 1, 1} }, }, { -- subject to special checks { { "mcl_compass:compass", 1, 1 }, {"mcl_shops:coin", 4, 5} }, }, { -- TODO: replace with empty map { { "mcl_shops:coin", 5, 10}, { "mcl_maps:filled_map", 1, 1 } }, }, -- TODO: special maps }, }, armorer = { name = N("Armorer"), texture = "mobs_mc_villager_smith.png", trades = { { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 4, 6 }, { "3d_armor:helmet_iron", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 1 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 7, 9 }, { "3d_armor:chestplate_iron", 1, 1 } }, }, { { { "mcl_core:diamond", 1, 1 }, {"mcl_shops:coin", 9, 9} }, -- TODO: enchant { { "mcl_shops:coin", 26, 28 }, { "3d_armor:chestplate_gold", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 2 }, { "3d_armor:boots_chain", 1, 1 } }, { { "mcl_shops:coin", 2, 3 }, { "3d_armor:leggings_chain", 1, 1 } }, { { "mcl_shops:coin", 1, 2 }, { "3d_armor:helmet_chain", 1, 1 } }, { { "mcl_shops:coin", 3, 4 }, { "3d_armor:chestplate_chain", 1, 1 } }, }, }, }, leatherworker = { name = N("Leatherworker"), texture = "mobs_mc_villager_butcher.png", trades = { { { { "mcl_mobitems:leather", 5, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 3, 5 }, { "3d_armor:leggings_leather", 2, 4 } }, }, { -- TODO: enchant { { "mcl_shops:coin", 4, 7 }, { "3d_armor:chestplate_leather", 1, 1 } }, }, { { { "mcl_shops:coin", 15, 20 }, { "mcl_mobitems:saddle", 1, 1 } }, }, }, }, butcher = { name = N("Butcher"), texture = "mobs_mc_villager_butcher.png", trades = { { { { "mcl_mobitems:beef", 5, 10 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_mobitems:chicken", 5, 10 }, {"mcl_shops:coin", 1, 1} }, }, { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, { {"mcl_shops:coin", 1, 1}, { "mcl_mobitems:cooked_beef", 5, 10 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_mobitems:cooked_chicken", 5, 10 } }, }, }, }, weapon_smith = { name = N("Weapon Smith"), texture = "mobs_mc_villager_smith.png", trades = { { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_shops:coin", 3, 4 }, { "mcl_tools:axe_iron", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 1 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchant { { "mcl_shops:coin", 2, 3 }, { "mcl_tools:sword_iron", 1, 1 } }, }, { { { "mcl_core:diamond", 1, 1 }, {"mcl_shops:coin", 9, 9 } }, -- TODO: enchant { { "mcl_shops:coin", 17, 19 }, { "mcl_tools:sword_diamond", 1, 1 } }, -- TODO: enchant { { "mcl_shops:coin", 27, 28 }, { "mcl_tools:axe_diamond", 1, 1 } }, }, }, }, tool_smith = { name = N("Tool Smith"), texture = "mobs_mc_villager_smith.png", trades = { { { { "mcl_core:coal_lump", 2, 3 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchant { { "mcl_shops:coin", 1, 1 }, { "mcl_tools:shovel_iron", 1, 1 } }, }, { { { "mcl_shops:coin", 1, 1 }, {"mcl_shops:coin", 1, 1} }, -- TODO: enchant { { "mcl_shops:coin", 2, 4 }, { "mcl_tools:pick_iron", 1, 1 } }, }, { { { "mcl_core:diamond", 1, 1 }, {"mcl_shops:coin", 9, 9 } }, -- TODO: enchant { { "mcl_shops:coin", 26, 28 }, { "mcl_tools:pick_diamond", 1, 1 } }, }, }, }, cleric = { name = N("Cleric"), texture = "mobs_mc_villager_priest.png", trades = { { { { "mcl_mobitems:rotten_flesh", 15, 25 }, {"mcl_shops:coin", 1, 1} }, { { "mcl_core:gold_ingot", 2, 2 }, {"mcl_shops:coin", 6, 6 } }, }, { { {"mcl_shops:coin", 1, 1}, { "mesecons:redstone", 1, 4 } }, { {"mcl_shops:coin", 1, 1}, { "mcl_dye:blue", 1, 2 } }, }, { { {"mcl_shops:coin", 1, 1}, { "mcl_nether:glowstone", 1, 3 } }, { { "mcl_shops:coin", 4, 7 }, { "mcl_throwing:ender_pearl", 1, 1 } }, TRADE_V6_RED_SANDSTONE, }, -- TODO: Bottle 'o enchanting }, }, nitwit = { name = N("Nitwit"), texture = "mobs_mc_villager.png", -- No trades for nitwit trades = nil, } } local profession_names = {} for id, _ in pairs(professions) do table.insert(profession_names, id) end local stand_still = function(self) self.walk_chance = 0 self.jump = false end local update_max_tradenum = function(self) if not self._trades then return end local trades = minetest.deserialize(self._trades) for t=1, #trades do local trade = trades[t] if trade.tier > self._max_trade_tier then self._max_tradenum = t - 1 return end end self._max_tradenum = #trades end local init_trader_vars = function(self) if not self._profession then -- Select random profession from all professions with matching clothing local texture = self.base_texture[1] local matches = {} for prof_id, prof in pairs(professions) do if texture == prof.texture then table.insert(matches, prof_id) end end local p = math.random(1, #matches) self._profession = matches[p] end if not self._max_trade_tier then self._max_trade_tier = 1 end if not self._locked_trades then self._locked_trades = 0 end if not self._trading_players then self._trading_players = {} end end local init_trades = function(self, inv) local profession = professions[self._profession] local trade_tiers = profession.trades if trade_tiers == nil then -- Empty trades self._trades = false return end local max_tier = #trade_tiers local trades = {} for tiernum=1, max_tier do local tier = trade_tiers[tiernum] for tradenum=1, #tier do local trade = tier[tradenum] local wanted1_item = trade[1][1] local wanted1_count = math.random(trade[1][2], trade[1][3]) local offered_item = trade[2][1] local offered_count = math.random(trade[2][2], trade[2][3]) local wanted = { wanted1_item .. " " ..wanted1_count } if trade[1][4] then local wanted2_item = trade[1][4] local wanted2_count = math.random(trade[1][5], trade[1][6]) table.insert(wanted, wanted2_item .. " " ..wanted2_count) end table.insert(trades, { wanted = wanted, offered = offered_item .. " " .. offered_count, tier = tiernum, -- tier of this trade traded_once = false, -- true if trade was traded at least once trade_counter = 0, -- how often the this trade was mate after the last time it got unlocked locked = false, -- if this trade is locked. Locked trades can't be used }) end end self._trades = minetest.serialize(trades) end local set_trade = function(trader, player, inv, concrete_tradenum) local trades = minetest.deserialize(trader._trades) if not trades then init_trades(trader) trades = minetest.deserialize(trader._trades) if not trades then minetest.log("error", "[mobs_mc] Failed to select villager trade!") return end end local name = player:get_player_name() -- Stop tradenum from advancing into locked tiers or out-of-range areas if concrete_tradenum > trader._max_tradenum then concrete_tradenum = trader._max_tradenum elseif concrete_tradenum < 1 then concrete_tradenum = 1 end player_tradenum[name] = concrete_tradenum local trade = trades[concrete_tradenum] inv:set_stack("wanted", 1, ItemStack(trade.wanted[1])) inv:set_stack("offered", 1, ItemStack(trade.offered)) if trade.wanted[2] then local wanted2 = ItemStack(trade.wanted[2]) inv:set_stack("wanted", 2, wanted2) else inv:set_stack("wanted", 2, "") end end local function show_trade_formspec(playername, trader, tradenum) if not trader._trades then return end if not tradenum then tradenum = 1 end local trades = minetest.deserialize(trader._trades) local trade = trades[tradenum] local profession = professions[trader._profession].name local disabled_img = "" if trade.locked then disabled_img = "image[4.3,2.52;1,1;mobs_mc_trading_formspec_disabled.png]".. "image[4.3,1.1;1,1;mobs_mc_trading_formspec_disabled.png]" end local tradeinv_name = "mobs_mc:trade_"..playername local tradeinv = minetest.formspec_escape("detached:"..tradeinv_name) local b_prev, b_next = "", "" if #trades > 1 then if tradenum > 1 then b_prev = "button[1,1;0.5,1;prev_trade;<]" end if tradenum < trader._max_tradenum then b_next = "button[7.26,1;0.5,1;next_trade;>]" end end local formspec = "size[9,8.75]" .."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]" ..disabled_img ..mcl_vars.inventory_header .."label[4,0;"..minetest.formspec_escape(minetest.colorize("#313131", S(profession))).."]" .."list[current_player;main;0,4.5;9,3;9]" .."list[current_player;main;0,7.74;9,1;]" ..b_prev..b_next .."list["..tradeinv..";wanted;2,1;2,1;]" .."list["..tradeinv..";offered;5.76,1;1,1;]" .."list["..tradeinv..";input;2,2.5;2,1;]" .."list["..tradeinv..";output;5.76,2.55;1,1;]" .."listring["..tradeinv..";output]" .."listring[current_player;main]" .."listring["..tradeinv..";input]" .."listring[current_player;main]" minetest.sound_play("mobs_mc_villager_trade", {to_player = playername}) minetest.show_formspec(playername, tradeinv_name, formspec) end local update_offer = function(inv, player, sound) local name = player:get_player_name() local trader = player_trading_with[name] local tradenum = player_tradenum[name] if not trader or not tradenum then return false end local trades = minetest.deserialize(trader._trades) if not trades then return false end local trade = trades[tradenum] if not trade then return false end local wanted1, wanted2 = inv:get_stack("wanted", 1), inv:get_stack("wanted", 2) local input1, input2 = inv:get_stack("input", 1), inv:get_stack("input", 2) -- BEGIN OF SPECIAL HANDLING OF COMPASS -- These 2 functions are a complicated check to check if the input contains a -- special item which we cannot check directly against their name, like -- compass. -- TODO: Remove these check functions when compass and clock are implemented -- as single items. local check_special = function(special_item, group, wanted1, wanted2, input1, input2) if minetest.registered_aliases[special_item] then special_item = minetest.registered_aliases[special_item] end if wanted1:get_name() == special_item then local check_input = function(input, wanted, group) return minetest.get_item_group(input:get_name(), group) ~= 0 and input:get_count() >= wanted:get_count() end if check_input(input1, wanted1, group) then return true elseif check_input(input2, wanted1, group) then return true else return false end end return false end -- Apply above function to all items which we consider special. -- This function succeeds if ANY item check succeeds. local check_specials = function(wanted1, wanted2, input1, input2) return check_special(COMPASS, "compass", wanted1, wanted2, input1, input2) end -- END OF SPECIAL HANDLING OF COMPASS if ( ((inv:contains_item("input", wanted1) and (wanted2:is_empty() or inv:contains_item("input", wanted2))) or -- BEGIN OF SPECIAL HANDLING OF COMPASS check_specials(wanted1, wanted2, input1, input2)) and -- END OF SPECIAL HANDLING OF COMPASS (trade.locked == false)) then inv:set_stack("output", 1, inv:get_stack("offered", 1)) if sound then minetest.sound_play("mobs_mc_villager_accept", {to_player = name}) end return true else inv:set_stack("output", 1, ItemStack("")) if sound then minetest.sound_play("mobs_mc_villager_deny", {to_player = name}) end return false end end -- Returns a single itemstack in the given inventory to the player's main inventory, or drop it when there's no space left local function return_item(itemstack, dropper, pos, inv_p) if dropper:is_player() then -- Return to main inventory if inv_p:room_for_item("main", itemstack) then inv_p:add_item("main", itemstack) else -- Drop item on the ground local v = dropper:get_look_dir() local p = {x=pos.x, y=pos.y+1.2, z=pos.z} p.x = p.x+(math.random(1,3)*0.2) p.z = p.z+(math.random(1,3)*0.2) local obj = minetest.add_item(p, itemstack) if obj then v.x = v.x*4 v.y = v.y*4 + 2 v.z = v.z*4 obj:set_velocity(v) obj:get_luaentity()._insta_collect = false end end else -- Fallback for unexpected cases minetest.add_item(pos, itemstack) end return itemstack end local return_fields = function(player) local name = player:get_player_name() local inv_t = minetest.get_inventory({type="detached", name = "mobs_mc:trade_"..name}) local inv_p = player:get_inventory() for i=1, inv_t:get_size("input") do local stack = inv_t:get_stack("input", i) return_item(stack, player, player:get_pos(), inv_p) stack:clear() inv_t:set_stack("input", i, stack) end inv_t:set_stack("output", 1, "") end minetest.register_on_player_receive_fields(function(player, formname, fields) if string.sub(formname, 1, 14) == "mobs_mc:trade_" then local name = player:get_player_name() if fields.quit then -- Get input items back return_fields(player) -- Reset internal "trading with" state local trader = player_trading_with[name] if trader then trader._trading_players[name] = nil end player_trading_with[name] = nil elseif fields.next_trade or fields.prev_trade then local trader = player_trading_with[name] if not trader or not trader.object:get_luaentity() then return end local trades = trader._trades if not trades then return end local dir = 1 if fields.prev_trade then dir = -1 end local tradenum = player_tradenum[name] + dir local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade_"..name}) set_trade(trader, player, inv, tradenum) update_offer(inv, player, false) show_trade_formspec(name, trader, player_tradenum[name]) end end end) minetest.register_on_leaveplayer(function(player) local name = player:get_player_name() return_fields(player) player_tradenum[name] = nil local trader = player_trading_with[name] if trader then trader._trading_players[name] = nil end player_trading_with[name] = nil end) -- Return true if player is trading with villager, and the villager entity exists local trader_exists = function(playername) local trader = player_trading_with[playername] return trader ~= nil and trader.object:get_luaentity() ~= nil end local trade_inventory = { allow_take = function(inv, listname, index, stack, player) if listname == "input" then return stack:get_count() elseif listname == "output" then if not trader_exists(player:get_player_name()) then return 0 end -- Only allow taking full stack local count = stack:get_count() if count == inv:get_stack(listname, index):get_count() then -- Also update output stack again. -- If input has double the wanted items, the -- output will stay because there will be still -- enough items in input after the trade local wanted1 = inv:get_stack("wanted", 1) local wanted2 = inv:get_stack("wanted", 2) local input1 = inv:get_stack("input", 1) local input2 = inv:get_stack("input", 2) wanted1:set_count(wanted1:get_count()*2) wanted2:set_count(wanted2:get_count()*2) -- BEGIN OF SPECIAL HANDLING FOR COMPASS local special_checks = function(wanted1, input1, input2) if wanted1:get_name() == COMPASS then local compasses = 0 if (minetest.get_item_group(input1:get_name(), "compass") ~= 0) then compasses = compasses + input1:get_count() end if (minetest.get_item_group(input2:get_name(), "compass") ~= 0) then compasses = compasses + input2:get_count() end return compasses >= wanted1:get_count() end return false end -- END OF SPECIAL HANDLING FOR COMPASS if (inv:contains_item("input", wanted1) and (wanted2:is_empty() or inv:contains_item("input", wanted2))) -- BEGIN OF SPECIAL HANDLING FOR COMPASS or special_checks(wanted1, input1, input2) then -- END OF SPECIAL HANDLING FOR COMPASS return -1 else -- If less than double the wanted items, -- remove items from output (final trade, -- input runs empty) return count end else return 0 end else return 0 end end, allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) if from_list == "input" and to_list == "input" then return count elseif from_list == "output" and to_list == "input" then if not trader_exists(player:get_player_name()) then return 0 end local move_stack = inv:get_stack(from_list, from_index) if inv:get_stack(to_list, to_index):item_fits(move_stack) then return count end end return 0 end, allow_put = function(inv, listname, index, stack, player) if listname == "input" then if not trader_exists(player:get_player_name()) then return 0 else return stack:get_count() end else return 0 end end, on_put = function(inv, listname, index, stack, player) update_offer(inv, player, true) end, on_move = function(inv, from_list, from_index, to_list, to_index, count, player) if from_list == "output" and to_list == "input" then inv:remove_item("input", inv:get_stack("wanted", 1)) local wanted2 = inv:get_stack("wanted", 2) if not wanted2:is_empty() then inv:remove_item("input", inv:get_stack("wanted", 2)) end minetest.sound_play("mobs_mc_villager_accept", {to_player = player:get_player_name()}) end update_offer(inv, player, true) end, on_take = function(inv, listname, index, stack, player) local accept local name = player:get_player_name() if listname == "output" then local wanted1 = inv:get_stack("wanted", 1) inv:remove_item("input", wanted1) local wanted2 = inv:get_stack("wanted", 2) if not wanted2:is_empty() then inv:remove_item("input", inv:get_stack("wanted", 2)) end -- BEGIN OF SPECIAL HANDLING FOR COMPASS if wanted1:get_name() == COMPASS then for n=1, 2 do local input = inv:get_stack("input", n) if minetest.get_item_group(input:get_name(), "compass") ~= 0 then input:set_count(input:get_count() - wanted1:get_count()) inv:set_stack("input", n, input) break end end end -- END OF SPECIAL HANDLING FOR COMPASS local trader = player_trading_with[name] local tradenum = player_tradenum[name] local trades if trader and trader._trades then trades = minetest.deserialize(trader._trades) end if trades then local trade = trades[tradenum] local unlock_stuff = false if not trade.traded_once then -- Unlock all the things if something was traded -- for the first time ever unlock_stuff = true trade.traded_once = true elseif trade.trade_counter == 0 and math.random(1,5) == 1 then -- Otherwise, 20% chance to unlock if used freshly reset trade unlock_stuff = true end local update_formspec = false if unlock_stuff then -- First-time trade unlock all trades and unlock next trade tier if trade.tier + 1 > trader._max_trade_tier then trader._max_trade_tier = trader._max_trade_tier + 1 update_max_tradenum(trader) update_formspec = true end for t=1, #trades do trades[t].locked = false trades[t].trade_counter = 0 end trader._locked_trades = 0 -- Also heal trader for unlocking stuff -- TODO: Replace by Regeneration I trader.health = math.min(trader.hp_max, trader.health + 4) end trade.trade_counter = trade.trade_counter + 1 -- Semi-randomly lock trade for repeated trade (not if there's only 1 trade) if trader._max_tradenum > 1 then if trade.trade_counter >= 12 then trade.locked = true elseif trade.trade_counter >= 2 then local r = math.random(1, math.random(4, 10)) if r == 1 then trade.locked = true end end end if trade.locked then inv:set_stack("output", 1, "") update_formspec = true trader._locked_trades = trader._locked_trades + 1 -- Check if we managed to lock ALL available trades. Rare but possible. if trader._locked_trades >= trader._max_tradenum then -- Emergency unlock! Unlock all other trades except the current one for t=1, #trades do if t ~= tradenum then trades[t].locked = false trades[t].trade_counter = 0 end end trader._locked_trades = 1 -- Also heal trader for unlocking stuff -- TODO: Replace by Regeneration I trader.health = math.min(trader.hp_max, trader.health + 4) end end trader._trades = minetest.serialize(trades) if update_formspec then show_trade_formspec(name, trader, tradenum) end else minetest.log("error", "[mobs_mc] Player took item from trader output but player_trading_with or player_tradenum is nil!") end accept = true elseif listname == "input" then update_offer(inv, player, false) end if accept then minetest.sound_play("mobs_mc_villager_accept", {to_player = name}) else minetest.sound_play("mobs_mc_villager_deny", {to_player = name}) end end, } minetest.register_on_joinplayer(function(player) local name = player:get_player_name() player_tradenum[name] = 1 player_trading_with[name] = nil -- Create or get player-specific trading inventory local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade_"..name}) if not inv then inv = minetest.create_detached_inventory("mobs_mc:trade_"..name, trade_inventory, name) end inv:set_size("input", 2) inv:set_size("output", 1) inv:set_size("wanted", 2) inv:set_size("offered", 1) end) --[=======[ MOB REGISTRATION AND SPAWNING ]=======] mobs:register_mob("mobs_mc:villager", { type = "npc", hp_min = 20, hp_max = 20, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_villager.b3d", textures = { { "mobs_mc_villager.png", "mobs_mc_villager.png", --hat }, { "mobs_mc_villager_farmer.png", "mobs_mc_villager_farmer.png", --hat }, { "mobs_mc_villager_priest.png", "mobs_mc_villager_priest.png", --hat }, { "mobs_mc_villager_librarian.png", "mobs_mc_villager_librarian.png", --hat }, { "mobs_mc_villager_butcher.png", "mobs_mc_villager_butcher.png", --hat }, { "mobs_mc_villager_smith.png", "mobs_mc_villager_smith.png", --hat }, }, visual_size = {x=3, y=3}, makes_footstep_sound = true, walk_velocity = 1.2, run_velocity = 2.4, drops = {}, -- TODO: sounds animation = { stand_speed = 25, stand_start = 40, stand_end = 59, walk_speed = 25, walk_start = 0, walk_end = 40, run_speed = 25, run_start = 0, run_end = 40, die_speed = 15, die_start = 210, die_end = 220, die_loop = false, }, water_damage = 0, lava_damage = 4, light_damage = 0, view_range = 16, fear_height = 4, jump = true, walk_chance = DEFAULT_WALK_CHANCE, on_rightclick = function(self, clicker) -- Initiate trading local name = clicker:get_player_name() self._trading_players[name] = true init_trader_vars(self) if self._trades == nil then init_trades(self) end update_max_tradenum(self) if self._trades == false then -- Villager has no trades, rightclick is a no-op return end player_trading_with[name] = self local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade_"..name}) set_trade(self, clicker, inv, 1) show_trade_formspec(name, self) -- Behaviour stuff: -- Make villager look at player and stand still local selfpos = self.object:get_pos() local clickerpos = clicker:get_pos() local dir = vector.direction(selfpos, clickerpos) self.object:set_yaw(minetest.dir_to_yaw(dir)) stand_still(self) end, _player_scan_timer = 0, _trading_players = {}, -- list of playernames currently trading with villager (open formspec) do_custom = function(self, dtime) -- Stand still if player is nearby. if not self._player_scan_timer then self._player_scan_timer = 0 end self._player_scan_timer = self._player_scan_timer + dtime -- Check infrequently to keep CPU load low if self._player_scan_timer > PLAYER_SCAN_INTERVAL then self._player_scan_timer = 0 local selfpos = self.object:get_pos() local objects = minetest.get_objects_inside_radius(selfpos, PLAYER_SCAN_RADIUS) local has_player = false for o, obj in pairs(objects) do if obj:is_player() then has_player = true break end end if has_player then minetest.log("verbose", "[mobs_mc] Player near villager found!") stand_still(self) else minetest.log("verbose", "[mobs_mc] No player near villager found!") self.walk_chance = DEFAULT_WALK_CHANCE self.jump = true end end end, on_spawn = function(self) init_trader_vars(self) end, on_die = function(self, pos) -- Close open trade formspecs and give input back to players local trading_players = self._trading_players for name, _ in pairs(trading_players) do minetest.close_formspec(name, "mobs_mc:trade_"..name) local player = minetest.get_player_by_name(name) if player then return_fields(player) end end end, }) mobs:spawn_specific("mobs_mc:villager", mobs_mc.spawn.village, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 8000, 4, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max) -- compatibility mobs:alias_mob("mobs:villager", "mobs_mc:villager") -- spawn eggs mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0) if minetest.settings:get_bool("log_mods") then minetest.log("action", "MC mobs loaded") end
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
/!\ ACHTUNG: /!\
Alle von mir gehosteten Server werden mindestens zeitweise von Freitag ( 22.11. ) 18 Uhr bis Samstag ( 23.11. ) 8 Uhr und von Sonntag ( 24.11. ) 8 - 12 Uhr NICHT ERREICHBAR SEIN !
bis Montag ( 25.11. ) 8 Uhr kann es zu Ausfällen und Neustarts kommen.
Ich kann während der gesamten Zeit nahezu kein Support bieten und hoffe, dass Ihr die Unannehmlichkeiten entschuldigen könnt
Grund ist eine temporäre Umlegung des Server-Laptop für Renovierungsarbeiten, die über das Wochenende ( vorallem Samstag ) statfinden.
Bei Verzögerungen und anderen Änderungen werde ich im [Server] [v5.1.0] German-MineClone2-server- und [Server] [v5.1.0] German-Vanilla-server-Forum-Thread bescheid geben ...
/!\
=> Vorgang beendet ... alle Server laufen wieder wie gewohnt mit mir als Admin ^^
Alle von mir gehosteten Server werden mindestens zeitweise von Freitag ( 22.11. ) 18 Uhr bis Samstag ( 23.11. ) 8 Uhr und von Sonntag ( 24.11. ) 8 - 12 Uhr NICHT ERREICHBAR SEIN !
bis Montag ( 25.11. ) 8 Uhr kann es zu Ausfällen und Neustarts kommen.
Ich kann während der gesamten Zeit nahezu kein Support bieten und hoffe, dass Ihr die Unannehmlichkeiten entschuldigen könnt
Grund ist eine temporäre Umlegung des Server-Laptop für Renovierungsarbeiten, die über das Wochenende ( vorallem Samstag ) statfinden.
Bei Verzögerungen und anderen Änderungen werde ich im [Server] [v5.1.0] German-MineClone2-server- und [Server] [v5.1.0] German-Vanilla-server-Forum-Thread bescheid geben ...
/!\
=> Vorgang beendet ... alle Server laufen wieder wie gewohnt mit mir als Admin ^^
Last edited by Walker on Mon Nov 25, 2019 03:53, edited 2 times in total.
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-22_06:00:07.tgz
Größe: 2.972.908.826 Bytes
Datum: 22.11.2019
Zeit: 06:00:07
File: Minetest_2019-11-22_06:00:07.tgz
Größe: 2.972.908.826 Bytes
Datum: 22.11.2019
Zeit: 06:00:07
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
/!\ ACHTUNG /!\
Ich ernenne jjk1 hiermit zu Co-Administrator über das Wochenende AUF ALLEN GERMAN-***-SERVERN
ER BEKOMMT DAMIT ALLE ERLAUBNISSE IM RAHMEN SEINER PRIVILEGIEN !
sollte jemand sich von ihm zu unrecht behandel fühlen, hat er NICHT das Recht mich ( z.B. bei ban ) um Wiederaufnahme seines Verfahren zu bitten und muss sich mit jjk1´s Urteil zufrieden geben !
ICH BIN ERST WIEDER AB MONTAG VERFÜGBAR, und übernehme damit auch erst wieder ab Montag 0 Uhr das Amt als Admin
Grund: Meine Abwesenheit aufgrund von Renovierungsarbeiten
/!\
=> Vorgang beendet ... alle Server laufen wieder wie gewohnt mit mir als Admin ^^
d.h. jjk1 ist wieder "einfacher Moderator" und ihr könnt wieder bei mir Beschwerde über ihn einreichen ( wehe euch !, er steht unter meinem Schutz AT ALL !!! ) ^^
Ich ernenne jjk1 hiermit zu Co-Administrator über das Wochenende AUF ALLEN GERMAN-***-SERVERN
ER BEKOMMT DAMIT ALLE ERLAUBNISSE IM RAHMEN SEINER PRIVILEGIEN !
sollte jemand sich von ihm zu unrecht behandel fühlen, hat er NICHT das Recht mich ( z.B. bei ban ) um Wiederaufnahme seines Verfahren zu bitten und muss sich mit jjk1´s Urteil zufrieden geben !
ICH BIN ERST WIEDER AB MONTAG VERFÜGBAR, und übernehme damit auch erst wieder ab Montag 0 Uhr das Amt als Admin
Grund: Meine Abwesenheit aufgrund von Renovierungsarbeiten
/!\
=> Vorgang beendet ... alle Server laufen wieder wie gewohnt mit mir als Admin ^^
d.h. jjk1 ist wieder "einfacher Moderator" und ihr könnt wieder bei mir Beschwerde über ihn einreichen ( wehe euch !, er steht unter meinem Schutz AT ALL !!! ) ^^
Last edited by Walker on Mon Nov 25, 2019 03:57, edited 2 times in total.
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server [Admin: jjk1
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-25_04:00:01.tgz
Größe: 2.972.908.826 Bytes
Datum: 25.11.2019
Zeit: 04:00:01
File: Minetest_2019-11-25_04:00:01.tgz
Größe: 2.972.908.826 Bytes
Datum: 25.11.2019
Zeit: 04:00:01
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
INFO:
Alle Server laufen wieder normal mit mir als Admin und jjk1 als Moderator ...
Alle Server laufen wieder normal mit mir als Admin und jjk1 als Moderator ...
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-11-29_05:08:27.tgz
Größe: 3.004.668.894 Bytes
Datum: 29.11.2019
Zeit: 05:08:27
File: Minetest_2019-11-29_05:08:27.tgz
Größe: 3.004.668.894 Bytes
Datum: 29.11.2019
Zeit: 05:08:27
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
Neues Backup wurde erfolgreich angelegt
File: Minetest_2019-12-02_05:00:00.tgz
Größe: 3.021.052.070 Bytes
Datum: 02.12.2019
Zeit: 05:00:00
File: Minetest_2019-12-02_05:00:00.tgz
Größe: 3.021.052.070 Bytes
Datum: 02.12.2019
Zeit: 05:00:00
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Re: [Server] [v5.1.0] German-MineClone2-server
ok, es wurden nun zur Netzwerk-Performenz-Steigerung folgende Werte geändert:
hoffen wir das es ( gerade meinen Creative, Ethereal und Carpathian Servern ) hilft ^^
desweiteren wurde ein Fix für die Engine eingereicht ( nicht von mir ^^ ), wo ich nur noch warten muss, bis entsprechende Versionen ( also mit dem Patch ) in dem Debian-/Ubuntu-Repositories stehen
Code: Select all
max_simultaneous_block_sends_per_client = 8
max_simultaneous_block_sends_server_total = 16
desweiteren wurde ein Fix für die Engine eingereicht ( nicht von mir ^^ ), wo ich nur noch warten muss, bis entsprechende Versionen ( also mit dem Patch ) in dem Debian-/Ubuntu-Repositories stehen
My YouTube-Site with Minetest-LetsPlays and some of my Servers: Carpathian Ethereal Vanilla Creative MineClone2 --- Discord
Who is online
Users browsing this forum: No registered users and 3 guests