[Server] [v5.1.0] German-MineClone2-server

jjk1
Member
 
Posts: 77
Joined: Sun Mar 10, 2019 17:00
In-game: jjk1

Re: [Server] [v5.1.0] German-MineClone2-server

by jjk1 » Sun Oct 27, 2019 10:20

"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"
 

jjk1
Member
 
Posts: 77
Joined: Sun Mar 10, 2019 17:00
In-game: jjk1

Re: [Server] [v5.1.0] German-MineClone2-server

by jjk1 » Sun Oct 27, 2019 10:21

"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
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Mon Oct 28, 2019 04:11

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
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Fri Nov 01, 2019 05:12

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
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Mon Nov 04, 2019 03:46

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
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Mon Nov 04, 2019 17:28

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
Last edited by Walker on Sat Nov 09, 2019 10:07, edited 1 time in total.
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Fri Nov 08, 2019 05:17

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
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Sun Nov 10, 2019 16:59

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:
Code: Select all
30000: German-Carpathian-server
30001: German-Ethereal-server
30002: German-Vanilla-server
30003: German-Creative-server
30004: German-MineClone2-server


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:
Code: Select all
30008: Deutscher-Halloween-Server ( für HarryMonrow )
30014: Momos-Haus-Traum ( für Momo )
30015: bartonewelt ( privat, Passwortschutz )


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:
Code: Select all
null
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Mon Nov 11, 2019 03:12

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
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Fri Nov 15, 2019 05:11

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
 

User avatar
Testperson
New member
 
Posts: 3
Joined: Sun Nov 17, 2019 16:05
GitHub: testperson-offiziell
In-game: Testperson

Re: [Server] German-MineClone2-server

by Testperson » Sun Nov 17, 2019 16:26

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 ;)


Soweit ich weiß gibt es doch einen Befehl, um den Text wer Administrator ist zu ändern. Klappt das nicht?
by Testperson

Discord: https://discord.gg/B2eTZ4
Ingame: Testperson ; Github: testperson-offiziell ; YouTube: TESTPERSON
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.1.0] German-MineClone2-server

by Walker » Mon Nov 18, 2019 03:16

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
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] German-MineClone2-server

by Walker » Mon Nov 18, 2019 03:18

Testperson wrote:
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 ;)


Soweit ich weiß gibt es doch einen Befehl, um den Text wer Administrator ist zu ändern. Klappt das nicht?
und welcher Befehl währe das !?
Ich dachte sowas muss in die minetest.conf !?!
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker
 

User avatar
Walker
Member
 
Posts: 447
Joined: Tue Oct 03, 2017 09:22
In-game: Walker

Re: [Server] [v5.0.0] German-MineClone2-server

by Walker » Tue Nov 19, 2019 04:53

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
ist der Code zu 0.55.1 kompatibel ?
 

Previous

Return to Servers



Who is online

Users browsing this forum: No registered users and 13 guests