diff --git a/docs/LICENSE_OF_DEPENDENCIES.md b/docs/LICENSE_OF_DEPENDENCIES.md
index c62c262c0e80186800be790d07d01290f70e1204..dfd5fc25191a16edefc3b987769d3f83e8603515 100644
--- a/docs/LICENSE_OF_DEPENDENCIES.md
+++ b/docs/LICENSE_OF_DEPENDENCIES.md
@@ -12,6 +12,7 @@ works:
 - github.com/boltdb/bolt [MIT](https://github.com/boltdb/bolt/blob/master/LICENSE)
 - github.com/bsm/sarama-cluster [MIT](https://github.com/bsm/sarama-cluster/blob/master/LICENSE)
 - github.com/cenkalti/backoff [MIT](https://github.com/cenkalti/backoff/blob/master/LICENSE)
+- github.com/chuckpreslar/rcon [MIT](https://github.com/chuckpreslar/rcon#license)
 - github.com/couchbase/go-couchbase [MIT](https://github.com/couchbase/go-couchbase/blob/master/LICENSE)
 - github.com/couchbase/gomemcached [MIT](https://github.com/couchbase/gomemcached/blob/master/LICENSE)
 - github.com/couchbase/goutils [MIT](https://github.com/couchbase/go-couchbase/blob/master/LICENSE)
diff --git a/plugins/inputs/all/all.go b/plugins/inputs/all/all.go
index 3bf98c9d972eb7fe31cedfa03108794bf28a90c6..0796a8422aafb62885b77f6a3047288da42d5842 100644
--- a/plugins/inputs/all/all.go
+++ b/plugins/inputs/all/all.go
@@ -45,6 +45,7 @@ import (
 	_ "github.com/influxdata/telegraf/plugins/inputs/mailchimp"
 	_ "github.com/influxdata/telegraf/plugins/inputs/memcached"
 	_ "github.com/influxdata/telegraf/plugins/inputs/mesos"
+	_ "github.com/influxdata/telegraf/plugins/inputs/minecraft"
 	_ "github.com/influxdata/telegraf/plugins/inputs/mongodb"
 	_ "github.com/influxdata/telegraf/plugins/inputs/mqtt_consumer"
 	_ "github.com/influxdata/telegraf/plugins/inputs/mysql"
diff --git a/plugins/inputs/minecraft/README.md b/plugins/inputs/minecraft/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..726f9a29eedceb9d68b142da46f17ad42931a479
--- /dev/null
+++ b/plugins/inputs/minecraft/README.md
@@ -0,0 +1,66 @@
+#  Minecraft Plugin
+
+This plugin uses the RCON protocol to collect [statistics](http://minecraft.gamepedia.com/Statistics) from a [scoreboard](http://minecraft.gamepedia.com/Scoreboard) on a
+Minecraft server.
+
+To enable [RCON](http://wiki.vg/RCON) on the minecraft server, add this to your server configuration in the `server.properties` file:
+
+```
+enable-rcon=true
+rcon.password=<your password>
+rcon.port=<1-65535>
+```
+
+To create a new scoreboard objective called `jump` on a minecraft server tracking the `stat.jump` criteria, run this command
+in the Minecraft console:
+
+`/scoreboard objectives add jump stat.jump`
+
+Stats are collected with the following RCON command, issued by the plugin:
+
+`/scoreboard players list *`
+
+### Configuration:
+```
+[[inputs.minecraft]]
+   # server address for minecraft
+   server = "localhost"
+   # port for RCON
+   port = "25575"
+   # password RCON for mincraft server
+   password = "replace_me"
+```
+
+### Measurements & Fields:
+
+*This plugin uses only one measurement, titled* `minecraft`
+
+- The field name is the scoreboard objective name.
+- The field value is the count of the scoreboard objective
+
+- `minecraft`
+    - `<objective_name>` (integer, count)
+
+### Tags:
+
+- The `minecraft` measurement:
+    - `server`: the Minecraft RCON server
+    - `player`: the Minecraft player
+
+
+### Sample Queries:
+
+Get the number of jumps per player in the last hour:
+```
+SELECT SPREAD("jump") FROM "minecraft" WHERE time > now() - 1h GROUP BY "player"
+```
+
+### Example Output:
+
+```
+$ telegraf --input-filter minecraft --test
+* Plugin: inputs.minecraft, Collection 1
+> minecraft,player=notch,server=127.0.0.1:25575 jumps=178i 1498261397000000000
+> minecraft,player=dinnerbone,server=127.0.0.1:25575 deaths=1i,jumps=1999i,cow_kills=1i 1498261397000000000
+> minecraft,player=jeb,server=127.0.0.1:25575 d_pickaxe=1i,damage_dealt=80i,d_sword=2i,hunger=20i,health=20i,kills=1i,level=33i,jumps=264i,armor=15i 1498261397000000000
+```
diff --git a/plugins/inputs/minecraft/internal/rcon/rcon.go b/plugins/inputs/minecraft/internal/rcon/rcon.go
new file mode 100644
index 0000000000000000000000000000000000000000..f17163f8b4f151f22967e7702021b3e029129afa
--- /dev/null
+++ b/plugins/inputs/minecraft/internal/rcon/rcon.go
@@ -0,0 +1,200 @@
+// Package rcon implements the communication protocol for communicating
+// with RCON servers. Tested and working with Valve game servers.
+package rcon
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"net"
+	"strings"
+)
+
+const (
+	PacketPaddingSize uint8 = 2 // Size of Packet's padding.
+	PacketHeaderSize  uint8 = 8 // Size of Packet's header.
+)
+
+const (
+	TerminationSequence = "\x00" // Null empty ASCII string suffix.
+)
+
+// Packet type constants.
+// https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Packet_Type
+const (
+	Exec          int32 = 2
+	Auth          int32 = 3
+	AuthResponse  int32 = 2
+	ResponseValue int32 = 0
+)
+
+// Rcon package errors.
+var (
+	ErrInvalidWrite        = errors.New("Failed to write the payload corretly to remote connection.")
+	ErrInvalidRead         = errors.New("Failed to read the response corretly from remote connection.")
+	ErrInvalidChallenge    = errors.New("Server failed to mirror request challenge.")
+	ErrUnauthorizedRequest = errors.New("Client not authorized to remote server.")
+	ErrFailedAuthorization = errors.New("Failed to authorize to the remote server.")
+)
+
+type Client struct {
+	Host       string   // The IP address of the remote server.
+	Port       int      // The Port the remote server's listening on.
+	Authorized bool     // Has the client been authorized by the server?
+	Connection net.Conn // The TCP connection to the server.
+}
+
+type Header struct {
+	Size      int32 // The size of the payload.
+	Challenge int32 // The challenge ths server should mirror.
+	Type      int32 // The type of request being sent.
+}
+
+type Packet struct {
+	Header Header // Packet header.
+	Body   string // Body of packet.
+}
+
+// Compile converts a packets header and body into its approriate
+// byte array payload, returning an error if the binary packages
+// Write method fails to write the header bytes in their little
+// endian byte order.
+func (p Packet) Compile() (payload []byte, err error) {
+	var size int32 = p.Header.Size
+	var buffer bytes.Buffer
+	var padding [PacketPaddingSize]byte
+
+	if err = binary.Write(&buffer, binary.LittleEndian, &size); nil != err {
+		return
+	} else if err = binary.Write(&buffer, binary.LittleEndian, &p.Header.Challenge); nil != err {
+		return
+	} else if err = binary.Write(&buffer, binary.LittleEndian, &p.Header.Type); nil != err {
+		return
+	}
+
+	buffer.WriteString(p.Body)
+	buffer.Write(padding[:])
+
+	return buffer.Bytes(), nil
+}
+
+// NewPacket returns a pointer to a new Packet type.
+func NewPacket(challenge, typ int32, body string) (packet *Packet) {
+	size := int32(len([]byte(body)) + int(PacketHeaderSize+PacketPaddingSize))
+	return &Packet{Header{size, challenge, typ}, body}
+}
+
+// Authorize calls Send with the appropriate command type and the provided
+// password.  The response packet is returned if authorization is successful
+// or a potential error.
+func (c *Client) Authorize(password string) (response *Packet, err error) {
+	if response, err = c.Send(Auth, password); nil == err {
+		if response.Header.Type == AuthResponse {
+			c.Authorized = true
+		} else {
+			err = ErrFailedAuthorization
+			response = nil
+			return
+		}
+	}
+
+	return
+}
+
+// Execute calls Send with the appropriate command type and the provided
+// command.  The response packet is returned if the command executed successfully
+// or a potential error.
+func (c *Client) Execute(command string) (response *Packet, err error) {
+	return c.Send(Exec, command)
+}
+
+// Sends accepts the commands type and its string to execute to the clients server,
+// creating a packet with a random challenge id for the server to mirror,
+// and compiling its payload bytes in the appropriate order. The resonse is
+// decompiled from its bytes into a Packet type for return. An error is returned
+// if send fails.
+func (c *Client) Send(typ int32, command string) (response *Packet, err error) {
+	if typ != Auth && !c.Authorized {
+		err = ErrUnauthorizedRequest
+		return
+	}
+
+	// Create a random challenge for the server to mirror in its response.
+	var challenge int32
+	binary.Read(rand.Reader, binary.LittleEndian, &challenge)
+
+	// Create the packet from the challenge, typ and command
+	// and compile it to its byte payload
+	packet := NewPacket(challenge, typ, command)
+	payload, err := packet.Compile()
+
+	var n int
+
+	if nil != err {
+		return
+	} else if n, err = c.Connection.Write(payload); nil != err {
+		return
+	} else if n != len(payload) {
+		err = ErrInvalidWrite
+		return
+	}
+
+	var header Header
+
+	if err = binary.Read(c.Connection, binary.LittleEndian, &header.Size); nil != err {
+		return
+	} else if err = binary.Read(c.Connection, binary.LittleEndian, &header.Challenge); nil != err {
+		return
+	} else if err = binary.Read(c.Connection, binary.LittleEndian, &header.Type); nil != err {
+		return
+	}
+
+	if packet.Header.Type == Auth && header.Type == ResponseValue {
+		// Discard, empty SERVERDATA_RESPOSE_VALUE from authorization.
+		c.Connection.Read(make([]byte, header.Size-int32(PacketHeaderSize)))
+
+		// Reread the packet header.
+		if err = binary.Read(c.Connection, binary.LittleEndian, &header.Size); nil != err {
+			return
+		} else if err = binary.Read(c.Connection, binary.LittleEndian, &header.Challenge); nil != err {
+			return
+		} else if err = binary.Read(c.Connection, binary.LittleEndian, &header.Type); nil != err {
+			return
+		}
+	}
+
+	if header.Challenge != packet.Header.Challenge {
+		err = ErrInvalidChallenge
+		return
+	}
+
+	body := make([]byte, header.Size-int32(PacketHeaderSize))
+
+	n, err = c.Connection.Read(body)
+
+	if nil != err {
+		return
+	} else if n != len(body) {
+		err = ErrInvalidRead
+		return
+	}
+
+	response = new(Packet)
+	response.Header = header
+	response.Body = strings.TrimRight(string(body), TerminationSequence)
+
+	return
+}
+
+// NewClient creates a new Client type, creating the connection
+// to the server specified by the host and port arguements. If
+// the connection fails, an error is returned.
+func NewClient(host string, port int) (client *Client, err error) {
+	client = new(Client)
+	client.Host = host
+	client.Port = port
+	client.Connection, err = net.Dial("tcp", fmt.Sprintf("%v:%v", client.Host, client.Port))
+	return
+}
diff --git a/plugins/inputs/minecraft/minecraft.go b/plugins/inputs/minecraft/minecraft.go
new file mode 100644
index 0000000000000000000000000000000000000000..d88f4373d3df030246451e36f1c897286d2fe89c
--- /dev/null
+++ b/plugins/inputs/minecraft/minecraft.go
@@ -0,0 +1,142 @@
+package minecraft
+
+import (
+	"fmt"
+	"regexp"
+	"strconv"
+
+	"github.com/influxdata/telegraf"
+	"github.com/influxdata/telegraf/plugins/inputs"
+)
+
+const sampleConfig = `
+  ## server address for minecraft
+  # server = "localhost"
+  ## port for RCON
+  # port = "25575"
+  ## password RCON for mincraft server
+  # password = ""
+`
+
+var (
+	playerNameRegex = regexp.MustCompile(`for\s([^:]+):-`)
+	scoreboardRegex = regexp.MustCompile(`(?U):\s(\d+)\s\((.*)\)`)
+)
+
+// Client is an interface for a client which gathers data from a minecraft server
+type Client interface {
+	Gather() ([]string, error)
+}
+
+// Minecraft represents a connection to a minecraft server
+type Minecraft struct {
+	Server   string
+	Port     string
+	Password string
+	client   Client
+}
+
+// Description gives a brief description.
+func (s *Minecraft) Description() string {
+	return "Collects scores from a minecraft server's scoreboard using the RCON protocol"
+}
+
+// SampleConfig returns our sampleConfig.
+func (s *Minecraft) SampleConfig() string {
+	return sampleConfig
+}
+
+// Gather uses the RCON protocal to collect player and
+// scoreboard stats from a minecraft server.
+func (s *Minecraft) Gather(acc telegraf.Accumulator) error {
+	if s.client == nil {
+		var err error
+		s.client, err = NewRCON(s.Server, s.Port, s.Password)
+		if err != nil {
+			return err
+		}
+	}
+
+	scores, err := s.client.Gather()
+	if err != nil {
+		return err
+	}
+
+	for _, score := range scores {
+		player, err := ParsePlayerName(score)
+		if err != nil {
+			return err
+		}
+		tags := map[string]string{
+			"player": player,
+			"server": s.Server + ":" + s.Port,
+		}
+
+		stats, err := ParseScoreboard(score)
+		if err != nil {
+			return err
+		}
+		var fields = make(map[string]interface{}, len(stats))
+		for _, stat := range stats {
+			fields[stat.Name] = stat.Value
+		}
+
+		acc.AddFields("minecraft", fields, tags)
+	}
+
+	return nil
+}
+
+// ParsePlayerName takes an input string from rcon, to parse
+// the player.
+func ParsePlayerName(input string) (string, error) {
+	playerMatches := playerNameRegex.FindAllStringSubmatch(input, -1)
+	if playerMatches == nil {
+		return "", fmt.Errorf("no player was matched")
+	}
+	return playerMatches[0][1], nil
+}
+
+// Score is an individual tracked scoreboard stat.
+type Score struct {
+	Name  string
+	Value int
+}
+
+// ParseScoreboard takes an input string from rcon, to parse
+// scoreboard stats.
+func ParseScoreboard(input string) ([]Score, error) {
+	scoreMatches := scoreboardRegex.FindAllStringSubmatch(input, -1)
+	if scoreMatches == nil {
+		return nil, fmt.Errorf("No scores found")
+	}
+
+	var scores []Score
+
+	for _, match := range scoreMatches {
+		number := match[1]
+		name := match[2]
+		n, err := strconv.Atoi(number)
+		// Not necessary in current state, because regex can only match integers,
+		// maybe become necessary if regex is modified to match more types of
+		// numbers
+		if err != nil {
+			return nil, fmt.Errorf("Failed to parse score")
+		}
+		s := Score{
+			Name:  name,
+			Value: n,
+		}
+		scores = append(scores, s)
+	}
+	return scores, nil
+}
+
+func init() {
+	inputs.Add("minecraft", func() telegraf.Input {
+		return &Minecraft{
+			Server: "localhost",
+			Port:   "25575",
+		}
+	})
+}
diff --git a/plugins/inputs/minecraft/minecraft_test.go b/plugins/inputs/minecraft/minecraft_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..664ad4e8185299d32d43991a64e6b136d00fc196
--- /dev/null
+++ b/plugins/inputs/minecraft/minecraft_test.go
@@ -0,0 +1,228 @@
+package minecraft
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+
+	"github.com/influxdata/telegraf/testutil"
+)
+
+// TestParsePlayerName tests different Minecraft RCON inputs for players
+func TestParsePlayerName(t *testing.T) {
+	// Test a valid input string to ensure player is extracted
+	input := "1 tracked objective(s) for divislight:- jumps: 178 (jumps)"
+	got, err := ParsePlayerName(input)
+	want := "divislight"
+	if err != nil {
+		t.Fatalf("player returned error. Error: %s\n", err)
+	}
+	if got != want {
+		t.Errorf("got %s\nwant %s\n", got, want)
+	}
+
+	// Test an invalid input string to ensure error is returned
+	input = ""
+	got, err = ParsePlayerName(input)
+	want = ""
+	if err == nil {
+		t.Fatal("Expected error when player not present. No error found.")
+	}
+	if got != want {
+		t.Errorf("got %s\n want %s\n", got, want)
+	}
+
+	// Test an invalid input string to ensure error is returned
+	input = "1 tracked objective(s) for 😂:- jumps: 178 (jumps)"
+	got, err = ParsePlayerName(input)
+	want = "😂"
+	if err != nil {
+		t.Fatalf("player returned error. Error: %s\n", err)
+	}
+	if got != want {
+		t.Errorf("got %s\n want %s\n", got, want)
+	}
+}
+
+// TestParseScoreboard tests different Minecraft RCON inputs for scoreboard stats.
+func TestParseScoreboard(t *testing.T) {
+	// test a valid input string to ensure stats are parsed correctly.
+	input := `1 tracked objective(s) for divislight:- jumps: 178 (jumps)- sword: 5 (sword)`
+	got, err := ParseScoreboard(input)
+	if err != nil {
+		t.Fatal("Unexpected error")
+	}
+
+	want := []Score{
+		{
+			Name:  "jumps",
+			Value: 178,
+		},
+		{
+			Name:  "sword",
+			Value: 5,
+		},
+	}
+
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Got: \n%#v\nWant: %#v", got, want)
+	}
+
+	// Tests a partial input string.
+	input = `1 tracked objective(s) for divislight:- jumps: (jumps)- sword: 5 (sword)`
+	got, err = ParseScoreboard(input)
+
+	if err != nil {
+		t.Fatal("Unexpected error")
+	}
+
+	want = []Score{
+		{
+			Name:  "sword",
+			Value: 5,
+		},
+	}
+
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Got: \n%#v\nWant:\n%#v", got, want)
+	}
+
+	// Tests an empty string.
+	input = ``
+	_, err = ParseScoreboard(input)
+	if err == nil {
+		t.Fatal("Expected input error, but error was nil")
+	}
+
+	// Tests when a number isn't an integer.
+	input = `1 tracked objective(s) for divislight:- jumps: 178.5 (jumps)- sword: 5 (sword)`
+	got, err = ParseScoreboard(input)
+	if err != nil {
+		t.Fatal("Unexpected error")
+	}
+
+	want = []Score{
+		{
+			Name:  "sword",
+			Value: 5,
+		},
+	}
+
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Got: \n%#v\nWant: %#v", got, want)
+	}
+
+	//Testing a real life data scenario with unicode characters
+	input = `7 tracked objective(s) for mauxlaim:- total_kills: 39 (total_kills)- "howdy doody": 37 (dalevel)- howdy: 37 (lvl)- jumps: 1290 (jumps)- iron_pickaxe: 284 (iron_pickaxe)- cow_kills: 1 (cow_kills)- "asdf": 37 (😂)`
+	got, err = ParseScoreboard(input)
+	if err != nil {
+		t.Fatal("Unexpected error")
+	}
+
+	want = []Score{
+		{
+			Name:  "total_kills",
+			Value: 39,
+		},
+		{
+			Name:  "dalevel",
+			Value: 37,
+		},
+		{
+			Name:  "lvl",
+			Value: 37,
+		},
+		{
+			Name:  "jumps",
+			Value: 1290,
+		},
+		{
+			Name:  "iron_pickaxe",
+			Value: 284,
+		},
+		{
+			Name:  "cow_kills",
+			Value: 1,
+		},
+		{
+			Name:  "😂",
+			Value: 37,
+		},
+	}
+
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Got: \n%#v\nWant: %#v", got, want)
+	}
+
+}
+
+type MockClient struct {
+	Result []string
+	Err    error
+}
+
+func (m *MockClient) Gather() ([]string, error) {
+	return m.Result, m.Err
+}
+
+func TestGather(t *testing.T) {
+	var acc testutil.Accumulator
+	testConfig := Minecraft{
+		Server: "biffsgang.net",
+		Port:   "25575",
+		client: &MockClient{
+			Result: []string{
+				`1 tracked objective(s) for divislight:- jumps: 178 (jumps)`,
+				`7 tracked objective(s) for mauxlaim:- total_kills: 39 (total_kills)- "howdy doody": 37 (dalevel)- howdy: 37 (lvl)- jumps: 1290 (jumps)- iron_pickaxe: 284 (iron_pickaxe)- cow_kills: 1 (cow_kills)- "asdf": 37 (😂)`,
+				`5 tracked objective(s) for torham:- total_kills: 29 (total_kills)- "howdy doody": 33 (dalevel)- howdy: 33 (lvl)- jumps: 263 (jumps)- "asdf": 33 (😂)`,
+			},
+			Err: nil,
+		},
+	}
+
+	err := testConfig.Gather(&acc)
+	if err != nil {
+		t.Fatalf("gather returned error. Error: %s\n", err)
+	}
+
+	tags := map[string]string{
+		"player": "divislight",
+		"server": "biffsgang.net:25575",
+	}
+
+	assertContainsTaggedStat(t, &acc, "minecraft", "jumps", 178, tags)
+	tags["player"] = "mauxlaim"
+	assertContainsTaggedStat(t, &acc, "minecraft", "cow_kills", 1, tags)
+	tags["player"] = "torham"
+	assertContainsTaggedStat(t, &acc, "minecraft", "total_kills", 29, tags)
+
+}
+
+func assertContainsTaggedStat(
+	t *testing.T,
+	acc *testutil.Accumulator,
+	measurement string,
+	field string,
+	expectedValue int,
+	tags map[string]string,
+) {
+	var actualValue int
+	for _, pt := range acc.Metrics {
+		if pt.Measurement == measurement && reflect.DeepEqual(pt.Tags, tags) {
+			for fieldname, value := range pt.Fields {
+				if fieldname == field {
+					actualValue = value.(int)
+					if value == expectedValue {
+						return
+					}
+					t.Errorf("Expected value %d\n got value %d\n", expectedValue, value)
+				}
+			}
+		}
+	}
+	msg := fmt.Sprintf(
+		"Could not find measurement \"%s\" with requested tags within %s, Actual: %d",
+		measurement, field, actualValue)
+	t.Fatal(msg)
+
+}
diff --git a/plugins/inputs/minecraft/rcon.go b/plugins/inputs/minecraft/rcon.go
new file mode 100644
index 0000000000000000000000000000000000000000..6dbed47ad9be6655167033b7795fccac25fb8a78
--- /dev/null
+++ b/plugins/inputs/minecraft/rcon.go
@@ -0,0 +1,88 @@
+package minecraft
+
+import (
+	"strconv"
+	"strings"
+
+	"github.com/influxdata/telegraf/plugins/inputs/minecraft/internal/rcon"
+)
+
+const (
+	// NoMatches is a sentinel value returned when there are no statistics defined on the
+	//minecraft server
+	NoMatches = `All matches failed`
+	// ScoreboardPlayerList is the command to see all player statistics
+	ScoreboardPlayerList = `scoreboard players list *`
+)
+
+// RCONClient is a representation of RCON command authorizaiton and exectution
+type RCONClient interface {
+	Authorize(password string) (*rcon.Packet, error)
+	Execute(command string) (*rcon.Packet, error)
+}
+
+// RCON represents a RCON server connection
+type RCON struct {
+	Server   string
+	Port     string
+	Password string
+	client   RCONClient
+}
+
+// NewRCON creates a new RCON
+func NewRCON(server, port, password string) (*RCON, error) {
+	client, err := newClient(server, port)
+	if err != nil {
+		return nil, err
+	}
+
+	return &RCON{
+		Server:   server,
+		Port:     port,
+		Password: password,
+		client:   client,
+	}, nil
+}
+
+func newClient(server, port string) (*rcon.Client, error) {
+	p, err := strconv.Atoi(port)
+	if err != nil {
+		return nil, err
+	}
+
+	return rcon.NewClient(server, p)
+}
+
+// Gather recieves all player scoreboard information and returns it per player.
+func (r *RCON) Gather() ([]string, error) {
+	if r.client == nil {
+		var err error
+		r.client, err = newClient(r.Server, r.Port)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if _, err := r.client.Authorize(r.Password); err != nil {
+		// Potentially a network problem where the client will need to be
+		// re-initialized
+		r.client = nil
+		return nil, err
+	}
+
+	packet, err := r.client.Execute(ScoreboardPlayerList)
+	if err != nil {
+		// Potentially a network problem where the client will need to be
+		// re-initialized
+		r.client = nil
+		return nil, err
+	}
+
+	if !strings.Contains(packet.Body, NoMatches) {
+		players := strings.Split(packet.Body, "Showing")
+		if len(players) > 1 {
+			return players[1:], nil
+		}
+	}
+
+	return []string{}, nil
+}
diff --git a/plugins/inputs/minecraft/rcon_test.go b/plugins/inputs/minecraft/rcon_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..0119398941b0358f7d2730b871e4c28679510612
--- /dev/null
+++ b/plugins/inputs/minecraft/rcon_test.go
@@ -0,0 +1,67 @@
+package minecraft
+
+import (
+	"testing"
+
+	"github.com/influxdata/telegraf/plugins/inputs/minecraft/internal/rcon"
+)
+
+type MockRCONClient struct {
+	Result *rcon.Packet
+	Err    error
+}
+
+func (m *MockRCONClient) Authorize(password string) (*rcon.Packet, error) {
+	return m.Result, m.Err
+}
+func (m *MockRCONClient) Execute(command string) (*rcon.Packet, error) {
+	return m.Result, m.Err
+}
+
+// TestRCONGather test the RCON gather function
+func TestRCONGather(t *testing.T) {
+	mock := &MockRCONClient{
+		Result: &rcon.Packet{
+			Body: `Showing 1 tracked objective(s) for divislight:- jumps: 178 (jumps)Showing 7 tracked objective(s) for mauxlaim:- total_kills: 39 (total_kills)- "howdy doody": 37 (dalevel)- howdy: 37 (lvl)- jumps: 1290 (jumps)- iron_pickaxe: 284 (iron_pickaxe)- cow_kills: 1 (cow_kills)- "asdf": 37 (😂)Showing 5 tracked objective(s) for torham:- total_kills: 29 (total_kills)- "howdy doody": 33 (dalevel)- howdy: 33 (lvl)- jumps: 263 (jumps)- "asdf": 33 (😂)`,
+		},
+		Err: nil,
+	}
+
+	want := []string{
+		` 1 tracked objective(s) for divislight:- jumps: 178 (jumps)`,
+		` 7 tracked objective(s) for mauxlaim:- total_kills: 39 (total_kills)- "howdy doody": 37 (dalevel)- howdy: 37 (lvl)- jumps: 1290 (jumps)- iron_pickaxe: 284 (iron_pickaxe)- cow_kills: 1 (cow_kills)- "asdf": 37 (😂)`,
+		` 5 tracked objective(s) for torham:- total_kills: 29 (total_kills)- "howdy doody": 33 (dalevel)- howdy: 33 (lvl)- jumps: 263 (jumps)- "asdf": 33 (😂)`,
+	}
+
+	client := &RCON{
+		Server:   "craftstuff.com",
+		Port:     "2222",
+		Password: "pass",
+		client:   mock,
+	}
+
+	got, err := client.Gather()
+	if err != nil {
+		t.Fatalf("Gather returned an error. Error %s\n", err)
+	}
+	for i, s := range got {
+		if want[i] != s {
+			t.Fatalf("Got %s at index %d, want %s at index %d", s, i, want[i], i)
+		}
+	}
+
+	client.client = &MockRCONClient{
+		Result: &rcon.Packet{
+			Body: "",
+		},
+		Err: nil,
+	}
+
+	got, err = client.Gather()
+	if err != nil {
+		t.Fatalf("Gather returned an error. Error %s\n", err)
+	}
+	if len(got) != 0 {
+		t.Fatalf("Expected empty slice of length %d, got slice of length %d", 0, len(got))
+	}
+}